#include "common.h"

#include "gflib/touchpanel.h"
#include "system/procsys.h"
#include "system/wipe.h"
#include "system/brightness.h"
#include "system/clact_util.h"
#include "system/arc_util.h"
#include "system/softsprite.h"
#include "system/render_oam.h"
#include "system/msgdata.h"
#include "system/fontproc.h"
#include "system/window.h"
#include "system/gra_tool.h"
#include "system/snd_tool.h"
#include "system/pmfprint.h"
#include "system/camera_move.h"

#include "msgdata/msg.naix"
#include "msgdata/msg_ev_pokeselect.h"

#include "first_poke_select.naix"
#include "../../field/field_cutin.naix"


#include "demo/first_poke_select.h"

#include "fps_se_def.h"


//BMP・フォント関連
#define BG_FONTBMP_X	( 2 )			// 文字面ビットマップsize
#define BG_FONTBMP_Y	( 19 )			// 文字面ビットマップsize
#define BG_FONTBMP_CX	( 27 )			// 文字面ビットマップsize
#define BG_FONTBMP_CY	( 4 )			// 文字面ビットマップsize

#define BG_GUIDEBMP_X	( 1 )			// 文字面ビットマップsize
#define BG_GUIDEBMP_Y	( 19 )			// 文字面ビットマップsize
#define BG_GUIDEBMP_CX	( 29 )			// 文字面ビットマップsize
#define BG_GUIDEBMP_CY	( 4 )			// 文字面ビットマップsize

#define BG_FONT_COLOR		( 0 )		// 枠用カラーパレット
#define BG_FONT_CG_OFS		( 512 )
#define BG_FONT_STR_COLOR	( 2 )		// フォント用カラーパレット
#define BG_FONTBMP_PRICOLOR	( GF_PRINTCOLOR_MAKE(1,2,15) )		//背景色あり
#define BG_FONTBMP_PRICOLOR2	( GF_PRINTCOLOR_MAKE(1,2,0) )	//背景色ぬき

#define BG_PAL_OFS	(3)

#define BALL_NUM	(3)

// カメラ設定
#define CAMERA_SHIFT_Y	( 0 )
#define CAMERA_SHIFT_Z	( /*0xe000*/0xe000 )
#define CAMERA_TARGET_X	( 0 )
#define CAMERA_TARGET_Y	( FX32_ONE*15 )
#define CAMERA_TARGET_Z	( 0 )
#define CAMERA_ANGLE_X	( -0x2340 )
#define CAMERA_ANGLE_Y	( 0 )
#define CAMERA_ANGLE_Z	( 0 )
#define CAMERA_PERS	( /*0xbe4*/0x11a4 )
#define CAMERA_DISTANCE	( 0x64000 )

#define ZOOM_CAM_ANGLE	( -0x1b20 )
#define ZOOM_CAM_PERS	( 0x1124 )
#define ZOOM_CAM_SHIFT	( 0x8000 )
#define ZOOM_CAM_DIST	( 0x4b000 )

#define ZOOM_UP_CAM_ANGLE	( -0x15e0 )
#define ZOOM_UP_CAM_PERS	( 0x1024 )
#define ZOOM_UP_CAM_SHIFT	( 0xc000 )
#define ZOOM_UP_CAM_DIST	( 0x3c000 )

#define ZOOM_SYNC	(8)
#define SEL_BALL_ROT_SYNC	(8)
#define ALPHA_VAL	(11)

//3D関連
#define TURN_TABLE_R	(FX32_ONE * 32)		//ターンテーブルの半径(中心からボールまでの距離)
#define BALL_R			(FX32_ONE * 13)		//ボールの半径
#define BTN_R			(FX32_ONE * 6)		//ボタンの半径（おおよそ）
#define BALL_OFS	(FX32_ONE * 14)		//ボールの底までのおおよその高さ

#define ROT_SPEED	(0x800)

//アクター
#define CLACT_SET_WORK_NUM	(BALL_NUM)
#define CLACT_RES_DATA_TBL_NUM	(BALL_NUM)
#define OAM_CHAR_ENTRY_NUM	(BALL_NUM)
#define OAM_PLTT_ENTRY_NUM	(BALL_NUM)

//ホワイトアウトシンク数
#define SUBDISP_WHITEOUT_SYNC	(10)
#define MAINDISP_WHITEOUT_SYNC	(16)


//アニメフレーム
#define RIGHT_LARGE_SWAY_START_FRAME	(40*FX32_ONE)
#define LEFT_SMALL_SWAY_START_FRAME		(80*FX32_ONE)

//メッセージスピード
#define MSG_SPEED_FAST	(1)

// 3Dオブジェクト数
enum{
	POKESELECT_BALL_EF,
	POKESELECT_TABLE,
	POKESELECT_TURN_TABLE,
	POKESELECT_BALL1,
	POKESELECT_BALL2,
	POKESELECT_BALL3,
	POKESELECT_3DOBJ_NUM
};

// 3Dオブジェクトリソース数
enum{
	RES_BALL_EF,
	RES_TABLE,
	RES_TURN_TABLE,
	RES_BALL,
	RES_3DOBJ_NUM
};

// 3Dアニメ数
enum{
	ANM_BALL_MOVE1,
	ANM_BALL_MOVE2,
	ANM_BALL_MOVE3,
	ANM_BALL_OPEN,
	ANM_BALL_EF,
	ANM_TURN_TABLE,
	ANM_NUM,
};

enum{
	BALL_MOVE_ALL_ANIME = 0,
	BALL_OPEN_ANIME,
	BALL_MOVE_FRONT_ANIME,
};

typedef enum{
	REV_NONE,
	REV_PLUS,
	REV_MINUS,
}REV_DIR;

enum {
	SEQ_FADE_IN = 0,
	SEQ_FADE_IN_WAIT,
	SEQ_SELECT_MSG,
	SEQ_CONFIRM_MSG,
	SEQ_MSG_WAIT,
	SEQ_CONTROL,
	SEQ_ROTATE,
	SEQ_DECIDE_MOVE,
	SEQ_SWAY_WAIT,
	SEQ_CANCEL_MOVE,
	SEQ_BALL_OPEN,
	SEQ_FADE_OUT_WAIT_SUB,
	SEQ_FADE_OUT_WAIT,
};

enum {
	CAM_ZOOM_NONE,
	CAM_ZOOM_OUT,
	CAM_ZOOM_UP,
};

typedef enum
{
	ZOOM_ST_OUT = 0,
	ZOOM_ST_IN,
	ZOOM_ST_UP,
}ZOOM_STATE;

typedef enum
{
	CONF_NONE_SEL = 0,
	CONF_SELECT,
	CONF_LAST_DECIDE,
}CONF_STATE;

typedef enum
{
	RCI_REQ_NONE,			//リクエストなし
	RCI_REQ_REV_LEFT,		//時計回りリクエスト
	RCI_REQ_REV_RIGHT,		//反時計回りリクエスト
	RCI_REQ_REV_ZOOM_LEFT,	//ズーム時計回りリクエスト
	RCI_REQ_REV_ZOOM_RIGHT,	//ズーム反時計回りリクエスト
	RCI_REQ_SELECT,			//3選択状態にする
	RCI_REQ_LAST_DECIDE,	//最終決定
	RCI_REQ_DECIDE,			//決定
	RCI_REQ_CANCEL,			//キャンセル(ズームアウト)
}RC_INPUT;

typedef struct RES_DATA_tag{
	void*					pResMdl;		// モデルﾃﾞｰﾀ
	NNSG3dResMdlSet*		pModelSet;		// モデルセット
	NNSG3dResMdl*			pModel;			// モデルリソース
	NNSG3dResTex*			pMdlTex;		// モデルに貼り付けるテクスチャ
}RES_DATA;

typedef struct OBJ_3D_DATA_tag{
	NNSG3dRenderObj			RenderObj;		// レンダーオブジェクト
	fx32 Frame;

	BOOL DrawFlag;
	VecFx32 Trans;
	VecFx32 Scal;
	u16 RotY;		// y軸回転
	u16 RotX;		// x軸回転
}OBJ_3D_DATA;

typedef struct ANM_DATA_tag
{
	void*					ResAnmPtr;		// アニメリソース
	NNSG3dAnmObj*			AnmObjPtr;			// アニメーションオブジェ
}ANM_DATA;


typedef struct POKE_ACT_tag
{
	CLACT_U_RES_MANAGER_PTR ResMan[CLACT_U_RES_MAX];
	CLACT_U_RES_OBJ_PTR 	ResObjTbl[BALL_NUM][CLACT_U_RES_MAX];
	void *PokeChar[BALL_NUM];
	void *PokePal[BALL_NUM];
	SOFT_SPRITE_ARC SpriteArc;
	CLACT_SET_PTR 	ClactSet;
	CLACT_U_EASYRENDER_DATA	RendData;
	CLACT_WORK_PTR			ClActWork[BALL_NUM];
}POKE_ACT;


typedef struct FPOKE_SEL_WORKtag
{
	int Seq;
	int HeapID;

	// BGL
	GF_BGL_INI *bgl;

	GF_G3DMAN *g3DMan;
	GF_CAMERA_PTR CameraPtr;
	VecFx32 CameraTarget;
	NNSFndAllocator Allocator;

	RES_DATA	ResData[RES_3DOBJ_NUM];

	OBJ_3D_DATA ObjData[POKESELECT_3DOBJ_NUM];
	ANM_DATA	AnmData[ANM_NUM];

	VecFx32 BallPos[BALL_NUM];

	u32 FrontBallNo;	//手前のボール番号

	s16 NowRot;
	s16 AddRot;

	GF_BGL_BMPWIN* MsgWin;		//博士のメッセージ
	GF_BGL_BMPWIN* GuideWin;	//説明メッセージ

	u8 WinType;
	u8 MsgSpeed;
	u8 MsgIndex;
	u8 SelBallRotSync;			//選択ボールの自転シンク数

	CONF_STATE Confirmation;
	ZOOM_STATE Zoom;

	STRBUF* StrBuff;

	POKE_ACT PokeAct;

	CAM_MOV_CNT_PTR	CamMovPtr;

	POKEMON_PARAM	*PokeParam[BALL_NUM];		//三匹のポケモンパラメータのアドレス

	int BallAnm;

	GXRgb edge_marking[8];

}FPOKE_SEL_WORK;

//前方宣言
static void SetupBG( GF_BGL_INI* bgl, const int inHeapID );
static void DelObjRes(POKE_ACT *PokeActPtr);
static void VBlankFunc( void* work );
static void SetVramBank( void );
static void SetOAM(const int inHeapID);
static void Setup3D( FPOKE_SEL_WORK *psel_ptr );
static void Draw(FPOKE_SEL_WORK *psel_ptr);
static void Draw3D( FPOKE_SEL_WORK *psel_ptr );
static void Create3DObj( FPOKE_SEL_WORK *psel_ptr);
static void Free3DAnm(FPOKE_SEL_WORK *psel_ptr);
static void Free3DObj(FPOKE_SEL_WORK *psel_ptr);
static void InitCamera( FPOKE_SEL_WORK *psel_ptr );
static void InitClact( FPOKE_SEL_WORK *psel_ptr );
static void Load3DObj( RES_DATA* pResData, const int inMdlDataIdx,
		const int inHeapID );
static void Make3DObj( OBJ_3D_DATA* pObjData, RES_DATA *pRes);
static void Load3DObjAnm( const int inMdlDataIdx, const int inHeapID,
						  NNSFndAllocator* pAllocator,
						  RES_DATA* inResDataPtr, ANM_DATA* outAnmData );
static void Add3DAnm(OBJ_3D_DATA* pObjData, ANM_DATA* pAnmData);
static void Remove3DAnm(OBJ_3D_DATA* pObjData, ANM_DATA* pAnmData);

static BOOL Play3DAnm(ANM_DATA* pAnmData);
static void Play3DAnmLoop(ANM_DATA* pAnmData, const ZOOM_STATE inZoomState);
static void SwayBall(FPOKE_SEL_WORK *psel_ptr);
static BOOL CheckSmallSwayFrame(FPOKE_SEL_WORK *psel_ptr);

static void Delete3DObj( RES_DATA* pResData );
static void Delete3DAnm( ANM_DATA* pAnmData, NNSFndAllocator* pAllocator );
static void Set3DObjTrans(OBJ_3D_DATA* pObjData,
				const fx32 inX, const fx32 inY, const fx32 inZ );
static void Set3DObjScale(OBJ_3D_DATA* pObjData,
				const fx32 inX, const fx32 inY, const fx32 inZ);
static void SetBallPos(FPOKE_SEL_WORK *psel_ptr);

static void DrawObj( OBJ_3D_DATA *data);
static void GetTRSMatrix( OBJ_3D_DATA *data, MtxFx43 *outMtx );
static BOOL AddRot(FPOKE_SEL_WORK *psel_ptr, const s16 inRot);
static void ResetBallPos(FPOKE_SEL_WORK *psel_ptr, const REV_DIR inRevDir);
static void MakeBmpWin( FPOKE_SEL_WORK *psel_ptr );
static void LoadBG(GF_BGL_INI * bgl, const int inHeapID);

static u8 PrintMsg( GF_BGL_BMPWIN* pBmp, const int inHeapID, const BOOL inWindow,
		const int inArcIdx, const int inMsgIdx, const GF_PRINTCOLOR inColor, const u32 inWait, STRBUF** ppStrBuf );
static void PrintMainDispMsg(FPOKE_SEL_WORK *psel_ptr, const int inMsgIdx);
static void FreeBmpWin( GF_BGL_BMPWIN *outBmpWin );

static RC_INPUT ControlInput(FPOKE_SEL_WORK *psel_ptr);
static RC_INPUT GetRevReq(const u8 inNo, const u8 inFrontNo, const ZOOM_STATE inZoom);
static u8 CheckBallHit(const VecFx32 *inBallList, const VecFx32 *inNear, const VecFx32 *inFar, const fx32 inRange);

static void SetupSubDispPoke(FPOKE_SEL_WORK *psel_ptr);
static void SetPokeGra( CLACT_U_RES_MANAGER_PTR man_obj_ptr,
						CLACT_U_RES_MANAGER_PTR man_pal_ptr,
						void *chr_buf, void *pal_buf,
						const u8 inCode);
static void SetPokeActor( POKE_ACT *ptr, const u8 inCode, const int inHeapID );
static void DispFrontBallPoke(FPOKE_SEL_WORK *psel_ptr);
static void HideAllPoke(POKE_ACT *pPokeAct );

static BOOL RotFrontBall(FPOKE_SEL_WORK *psel_ptr, const int inOrgAng, const int inDstAng);
static u16 ChangeAngle(const int *org, const int *dst, const u8 now_sync, const u8 total_sync );

#ifdef PM_DEBUG
static void DebugPritnfCameraInfo(GF_CAMERA_PTR camera_ptr);
static void DebugCameraInput(GF_CAMERA_PTR camera_ptr);

static u8 test_anti_alias = 1;
static int test_alpha = ALPHA_VAL;
#endif //PM_DEBUG


static const int FirstMonsNo[BALL_NUM] = {152,155,158};

//----------------------------------------------------------------------------
/**
 *
 *	@brief	プロセス初期化
 *
 *	@param	proc		プロックデータ
 *	@param	seq			シーケンス
 *
 *	@return	処理状況
 *
 *	typedef enum {
 *		PROC_RES_CONTINUE = 0,		///<動作継続中
 *		PROC_RES_FINISH,			///<動作終了
 *	}PROC_RESULT;
 *
 *
 */
//-----------------------------------------------------------------------------
PROC_RESULT FirstPokeSelect_ProcInit( PROC* proc, int* seq )
{
	FPOKE_SEL_WORK *psel_ptr;
	GF_BGL_SYS_HEADER bg_header;
	//ヒープ作成
	sys_CreateHeap( HEAPID_BASE_APP, HEAPID_EV_POKESELECT, 0x40000 );
	//ワーク確保
	psel_ptr = PROC_AllocWork( proc, sizeof(FPOKE_SEL_WORK), HEAPID_EV_POKESELECT );
	MI_CpuClear8( psel_ptr, sizeof(FPOKE_SEL_WORK));

	psel_ptr->HeapID = HEAPID_EV_POKESELECT;
	//アロケータ作成
	sys_InitAllocator( &psel_ptr->Allocator, psel_ptr->HeapID, 32 );
	//外部データ取得
	{
		int i;
		POKESELECT_PEARENT_DATA* parent;
		parent = PROC_GetParentWork( proc );
		//ウィンドウタイプ
		psel_ptr->WinType = CONFIG_GetWindowType( parent->Config );
		//ポケモンパラムアドレス格納
		for(i=0;i<BALL_NUM;i++){
			psel_ptr->PokeParam[i] = &parent->PokeParam[i];
		}
	}
	//メッセージスピード
	psel_ptr->MsgSpeed = MSG_SPEED_FAST;

	// VBlank HBlank設定
	sys_VBlankFuncChange( VBlankFunc, psel_ptr );	// VBlankセット
	sys_HBlankIntrStop();	//HBlank割り込み停止

	//バンク割り当て
	SetVramBank();
	//OAM
	SetOAM(psel_ptr->HeapID);
	//3D関連
	Setup3D( psel_ptr );


	// BG面設定
	{
		GF_BGL_SYS_HEADER bg_header;
		psel_ptr->bgl = GF_BGL_BglIniAlloc( psel_ptr->HeapID );
		bg_header.dispMode	= GX_DISPMODE_GRAPHICS;
		bg_header.bgMode	= GX_BGMODE_0;
		bg_header.bgModeSub	= GX_BGMODE_1;
		bg_header.bg0_2Dor3D= GX_BG0_AS_3D;
		GF_BGL_InitBG( &bg_header );
		SetupBG( psel_ptr->bgl, psel_ptr->HeapID );
		// 表示
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG0, VISIBLE_ON );
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_OFF );	//下画面メッセージ面は隠しておく
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_OFF );	//下画面メッセージ面は隠しておく

		//下画面をメインにする
		sys.disp3DSW = DISP_3D_TO_SUB;
		GF_Disp_DispSelect();
	}

	//MSGプリント初期化
	MSG_PrintInit();

	// 文字列面作成
	MakeBmpWin( psel_ptr );
	//BGロード
	LoadBG( psel_ptr->bgl, psel_ptr->HeapID );

	// セルアクター
	InitClact( psel_ptr );

	// 3Dモデル生成
	Create3DObj( psel_ptr );

	// カメラ作成
	// カメラアロック
	psel_ptr->CameraPtr = GFC_AllocCamera( psel_ptr->HeapID );
	psel_ptr->CamMovPtr = CamMove_Init(psel_ptr->HeapID, psel_ptr->CameraPtr);
	InitCamera( psel_ptr );

	//ボールの位置設定
	SetBallPos( psel_ptr );

	//サブ画面に出すポケモンのセットアップ
	SetupSubDispPoke(psel_ptr);

	//メッセージプリント設定
	MsgPrintSkipFlagSet(MSG_SKIP_OFF);
	MsgPrintAutoFlagSet(MSG_AUTO_ON);
	MsgPrintTouchPanelFlagSet(MSG_TP_OFF);

	return PROC_RES_FINISH;
}

//----------------------------------------------------------------------------
/**
 *
 *	@brief	プロセスメイン
 *
 *	@param	proc		プロックデータ
 *	@param	seq			シーケンス
 *
 *	@return	処理状況
 *
 *	typedef enum {
 *		PROC_RES_CONTINUE = 0,		///<動作継続中
 *		PROC_RES_FINISH,			///<動作終了
 *	}PROC_RESULT;
 *
 *
 */
//-----------------------------------------------------------------------------
PROC_RESULT FirstPokeSelect_ProcMain( PROC* proc, int* seq )
{
	u8 zoom;
	FPOKE_SEL_WORK *psel_ptr = PROC_GetWork( proc );

	zoom = CAM_ZOOM_NONE;

	switch(*seq){
	case SEQ_FADE_IN:
		//した画面メッセージ作っておく
		PrintMainDispMsg(psel_ptr, EV_POKESELECT_08);
		//下メイン画面メッセージ非表示
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_OFF );
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_OFF );

		WIPE_SYS_Start(
			WIPE_PATTERN_WMS,
			WIPE_TYPE_FADEIN,
			WIPE_TYPE_FADEIN,
			WIPE_FADE_BLACK,
			COMM_BRIGHTNESS_SYNC,1,
			psel_ptr->HeapID );
		(*seq) = SEQ_FADE_IN_WAIT;
		break;
	case SEQ_FADE_IN_WAIT:
		if ( WIPE_SYS_EndCheck() ){
			(*seq) = SEQ_SELECT_MSG;
		}
		break;
	case SEQ_SELECT_MSG:
		//ズームアウトが終了していない場合は、処理を待つ
		if ( !CamMove_CheckFinished(psel_ptr->CamMovPtr) ){
			break;
		}
		//好きなボールをえらんでタッチ
		psel_ptr->MsgIndex = PrintMsg( psel_ptr->MsgWin, psel_ptr->HeapID, TRUE,
				NARC_msg_ev_pokeselect_dat, EV_POKESELECT_00, BG_FONTBMP_PRICOLOR, psel_ptr->MsgSpeed, &psel_ptr->StrBuff );
		//下メイン画面メッセージ非表示
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_OFF );
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_OFF );
		(*seq) = SEQ_MSG_WAIT;
		break;
	case SEQ_CONFIRM_MSG:
		//〜ポケモン〜だね？
		psel_ptr->MsgIndex = PrintMsg( psel_ptr->MsgWin, psel_ptr->HeapID, TRUE,
				NARC_msg_ev_pokeselect_dat, EV_POKESELECT_02 + psel_ptr->FrontBallNo, BG_FONTBMP_PRICOLOR, psel_ptr->MsgSpeed, &psel_ptr->StrBuff );
		//下メイン画面メッセージ表示
		PrintMainDispMsg(psel_ptr, EV_POKESELECT_09);
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_ON );
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_ON );
		(*seq) = SEQ_MSG_WAIT;
		break;
	case SEQ_MSG_WAIT:
		//メッセージ終了待ち
		if( GF_MSG_PrintEndCheck( psel_ptr->MsgIndex ) == 0 ){
			STRBUF_Delete( psel_ptr->StrBuff );
			psel_ptr->StrBuff = NULL;
			(*seq) = SEQ_CONTROL;
		}
		break;
	case SEQ_CONTROL:
		{
			RC_INPUT req;

			//ズームが終了していない場合は、処理を待つ
			if ( !CamMove_CheckFinished(psel_ptr->CamMovPtr) ){
				break;
			}

#ifdef PM_DEBUG
			//デバッグ（カメラ設定）
			if (sys.cont & PAD_BUTTON_L){
				DebugCameraInput(psel_ptr->CameraPtr);
				break;
			}else if(sys.trg & PAD_BUTTON_SELECT){
				//カメラ戻す
				InitCamera( psel_ptr );
				break;
			}else if(sys.trg & PAD_BUTTON_X){
				//カメラ情報表示
				DebugPritnfCameraInfo(psel_ptr->CameraPtr);
			}else if(sys.trg & PAD_BUTTON_START){
				test_anti_alias = (test_anti_alias+1)%2;
				G3X_AntiAlias(test_anti_alias);
				OS_Printf("anti=%d\n",test_anti_alias);
			}

			if (sys.cont & PAD_BUTTON_R){
				if (sys.trg & PAD_KEY_UP){
					test_alpha = (test_alpha+1)%16;
					OS_Printf("test_alpha = %d\n",test_alpha);
					//アルファセット
					G2S_SetBlendAlpha( GX_BLEND_PLANEMASK_BG2,
						GX_BLEND_PLANEMASK_BG1|GX_BLEND_PLANEMASK_BD, 0, test_alpha );
				}
				if (sys.trg & PAD_KEY_DOWN){
					int test;
					test = 15-test_alpha;
					test = (test+1)%16;
					test_alpha = 15 - test;
					OS_Printf("test_alpha = %d\n",test_alpha);
					//アルファセット
					G2S_SetBlendAlpha( GX_BLEND_PLANEMASK_BG2,
						GX_BLEND_PLANEMASK_BG1|GX_BLEND_PLANEMASK_BD, 0, test_alpha );
				}
			}
#endif	//PM_DEBUG

			req = ControlInput(psel_ptr);
			//ズームが必要かを判定
			switch(req){
			case RCI_REQ_CANCEL:			//キャンセル(ズームアウト)
				zoom = CAM_ZOOM_OUT;
				break;
			case RCI_REQ_DECIDE:
				zoom = CAM_ZOOM_UP;
				break;
			default:
				zoom = CAM_ZOOM_NONE;
			}

			switch(req){
			case RCI_REQ_SELECT:
				//アニメ変更
				psel_ptr->BallAnm = BALL_MOVE_FRONT_ANIME;
				{
					STRBUF* strbuf = NULL;
					PrintMsg( psel_ptr->MsgWin, psel_ptr->HeapID, FALSE,
							NARC_msg_ev_pokeselect_dat, EV_POKESELECT_05+psel_ptr->FrontBallNo,
							BG_FONTBMP_PRICOLOR, MSG_ALLPUT, &strbuf );
					STRBUF_Delete( strbuf );
					//鳴き声再生
					//PLATINUM_MERGE form指定追加 ここは0でいい筈
					Snd_PMVoicePlay( FirstMonsNo[psel_ptr->FrontBallNo] ,0);
					//下メイン画面メッセージ表示
					PrintMainDispMsg(psel_ptr, EV_POKESELECT_08);
					GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_ON );
					GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_ON );
				}
				//とりあえず
				DispFrontBallPoke(psel_ptr);
				(*seq) = SEQ_CONTROL;
				break;
			case RCI_REQ_REV_LEFT:
			case RCI_REQ_REV_ZOOM_LEFT:
				//時計回転(Y軸マイナス)
				psel_ptr->AddRot = -ROT_SPEED;
				(*seq) = SEQ_ROTATE;
				//SE
				Snd_SePitchPlay( SE_ROTATE, -(64*8) );
				break;
			case RCI_REQ_REV_RIGHT:
			case RCI_REQ_REV_ZOOM_RIGHT:
				//反時計回転(Y軸プラス)
				psel_ptr->AddRot = ROT_SPEED;
				(*seq) = SEQ_ROTATE;
				//SE
				Snd_SePitchPlay( SE_ROTATE, -(64*8) );
				break;
			case RCI_REQ_DECIDE:
				//下メイン画面メッセージ非表示
				GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_OFF );
				GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_OFF );
				(*seq) = SEQ_DECIDE_MOVE;
				break;
			case RCI_REQ_LAST_DECIDE:
				//ボール開くアニメ準備
				Remove3DAnm(&psel_ptr->ObjData[ POKESELECT_BALL1+psel_ptr->FrontBallNo ],
							&psel_ptr->AnmData[ANM_BALL_MOVE1+psel_ptr->FrontBallNo]);
				Add3DAnm(&psel_ptr->ObjData[ POKESELECT_BALL1+psel_ptr->FrontBallNo ], &psel_ptr->AnmData[ANM_BALL_OPEN]);
				Add3DAnm(&psel_ptr->ObjData[ POKESELECT_BALL_EF ], &psel_ptr->AnmData[ANM_BALL_EF]);
				//エフェクト表示
				psel_ptr->ObjData[ POKESELECT_BALL_EF ].DrawFlag = TRUE;
				(*seq) = SEQ_BALL_OPEN;
				break;
			case RCI_REQ_CANCEL:
				if (psel_ptr->Confirmation == CONF_LAST_DECIDE){
					//アニメ変更
					psel_ptr->BallAnm = BALL_MOVE_ALL_ANIME;
					//下画面メッセージ作っておく
					PrintMainDispMsg(psel_ptr, EV_POKESELECT_08);
					//下メイン画面メッセージ非表示
					GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_OFF );
					GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_OFF );
					//とりあえず
					HideAllPoke(&psel_ptr->PokeAct);
					//確認状態解除
					psel_ptr->Confirmation = CONF_NONE_SEL;
					(*seq) = SEQ_CANCEL_MOVE;
				}
				break;
			}
		}

		break;
	case SEQ_ROTATE:				//回転中
		if ( AddRot(psel_ptr, psel_ptr->AddRot) ){
			//アニメ変更
			psel_ptr->BallAnm = BALL_MOVE_FRONT_ANIME;
			//回転終了したあと手前のポケの情報表示
			{
				STRBUF* strbuf = NULL;
				PrintMsg( psel_ptr->MsgWin, psel_ptr->HeapID, FALSE,
						NARC_msg_ev_pokeselect_dat, EV_POKESELECT_05+psel_ptr->FrontBallNo, BG_FONTBMP_PRICOLOR, MSG_ALLPUT, &strbuf );
				STRBUF_Delete( strbuf );
				//鳴き声再生
				//PLATINUM_MERGE form指定追加 ここは0でいい筈
				Snd_PMVoicePlay( FirstMonsNo[psel_ptr->FrontBallNo] ,0 );
			}
			if (psel_ptr->Confirmation != CONF_SELECT){
				//※ここで、メッセージ生成すると処理落ちがきになるので、前もって作って隠しておくようにしてあります。
				//下メイン画面メッセージ表示
				GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_ON );
				GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_ON );
			}
			//とりあえず
			DispFrontBallPoke(psel_ptr);
			psel_ptr->Confirmation = CONF_SELECT;
			(*seq) = SEQ_CONTROL;
		}
		break;
	case SEQ_DECIDE_MOVE:
		//ボールとの1対1フェーズに移行
		if ( RotFrontBall(psel_ptr, 0, ZOOM_UP_CAM_ANGLE) ){
			//とりあえず
			DispFrontBallPoke(psel_ptr);
			(*seq) = SEQ_SWAY_WAIT;
		}
		break;
	case SEQ_SWAY_WAIT:
		if ( CheckSmallSwayFrame(psel_ptr) ){
			//確認状態へ
			psel_ptr->Confirmation = CONF_LAST_DECIDE;
			(*seq) = SEQ_CONFIRM_MSG;
		}
		break;
	case SEQ_CANCEL_MOVE:
		//開始フェーズに移行
		if ( RotFrontBall(psel_ptr, ZOOM_UP_CAM_ANGLE, 0) ){
			//ボール再配置
			ResetBallPos(psel_ptr, REV_NONE);
			(*seq) = SEQ_SELECT_MSG;
		}
		break;
	case SEQ_BALL_OPEN:
		//サブ画面ホワイトアウト
		WIPE_SYS_Start(
			WIPE_PATTERN_S,
			WIPE_TYPE_FADEOUT,
			WIPE_TYPE_FADEOUT,
			WIPE_FADE_WHITE,
			SUBDISP_WHITEOUT_SYNC,1,
			psel_ptr->HeapID );
		//ボール開くアニメ
		psel_ptr->BallAnm = BALL_OPEN_ANIME;
		//ズームアウトリクエスト
		{
			CAMERA_MOVE_PARAM param;
			VecFx32 shift = {0,0,CAMERA_SHIFT_Z};
			param.Angle = CAMERA_ANGLE_X;
			param.PerspWay = CAMERA_PERS;
			param.Length = shift;
			param.Distance = CAMERA_DISTANCE;
			CamMove_Request(psel_ptr->CamMovPtr, &param, ZOOM_SYNC);
		}
		(*seq) = SEQ_FADE_OUT_WAIT_SUB;
		//SE
		Snd_SePlay( SE_BALL_OPEN );
		break;
	case SEQ_FADE_OUT_WAIT_SUB:
		//サブ画面フェードアウト待ち
		if ( WIPE_SYS_EndCheck() ){
			//メイン画面フェードアウト
			WIPE_SYS_Start(
				WIPE_PATTERN_M,
				WIPE_TYPE_FADEOUT,
				WIPE_TYPE_FADEOUT,
				WIPE_FADE_WHITE,
				MAINDISP_WHITEOUT_SYNC,1,
				psel_ptr->HeapID );

			(*seq) = SEQ_FADE_OUT_WAIT;
		}
		break;
	case SEQ_FADE_OUT_WAIT:
		//フェードアウト待ち
		if ( WIPE_SYS_EndCheck() ){
			return PROC_RES_FINISH;		//プロセス終了処理へ
		}
		break;
	}

	//ズーム処理
	if (zoom != CAM_ZOOM_NONE){
		CAMERA_MOVE_PARAM param;
		if(zoom == CAM_ZOOM_OUT){				//ズームアウト
			VecFx32 shift = {0,0,CAMERA_SHIFT_Z};
			param.Angle = CAMERA_ANGLE_X;
			param.PerspWay = CAMERA_PERS;
			param.Length = shift;
			param.Distance = CAMERA_DISTANCE;

			psel_ptr->Zoom = ZOOM_ST_OUT;
		}else{									//ズームアップ(zoom == CAM_ZOOM_UP)
			VecFx32 shift = {0,0,ZOOM_UP_CAM_SHIFT};
			param.Angle = ZOOM_UP_CAM_ANGLE;
			param.PerspWay = ZOOM_UP_CAM_PERS;
			param.Length = shift;
			param.Distance = ZOOM_UP_CAM_DIST;

			psel_ptr->Zoom = ZOOM_ST_UP;
		}
		CamMove_Request(psel_ptr->CamMovPtr, &param, ZOOM_SYNC);
	}

	if (psel_ptr->BallAnm == BALL_OPEN_ANIME){
		Play3DAnm(&psel_ptr->AnmData[ANM_BALL_OPEN]);
		Play3DAnm(&psel_ptr->AnmData[ANM_BALL_EF]);
	}else if(psel_ptr->BallAnm == BALL_MOVE_FRONT_ANIME){
		SwayBall(psel_ptr);
	}else{
		//とりあえずアニメ停止
		psel_ptr->AnmData[0].AnmObjPtr->frame = 0;
		psel_ptr->AnmData[1].AnmObjPtr->frame = 0;
		psel_ptr->AnmData[2].AnmObjPtr->frame = 0;
	}

	//ターンテーブルアニメ
	{
		ANM_DATA* anm_data;
		anm_data = &psel_ptr->AnmData[ANM_TURN_TABLE];
		anm_data->AnmObjPtr->frame += (FX32_ONE);
		if ( anm_data->AnmObjPtr->frame >= NNS_G3dAnmObjGetNumFrame(anm_data->AnmObjPtr) ){
			anm_data->AnmObjPtr->frame = 0;
		}
	}

	Draw(psel_ptr);

	return PROC_RES_CONTINUE;
}

//----------------------------------------------------------------------------
/**
 *
 *	@brief	プロセス終了
 *
 *	@param	proc		プロックデータ
 *	@param	seq			シーケンス
 *
 *	@return	処理状況
 *
 *	typedef enum {
 *		PROC_RES_CONTINUE = 0,		///<動作継続中
 *		PROC_RES_FINISH,			///<動作終了
 *	}PROC_RESULT;
 *
 *
 */
//-----------------------------------------------------------------------------
PROC_RESULT FirstPokeSelect_ProcEnd( PROC* proc, int* seq )
{
	FPOKE_SEL_WORK *psel_ptr = PROC_GetWork( proc );
	POKESELECT_PEARENT_DATA* parent =PROC_GetParentWork( proc );

	//メッセージプリント設定をリセット
	MsgPrintSkipFlagSet(MSG_SKIP_OFF);
	MsgPrintAutoFlagSet(MSG_AUTO_OFF);
	MsgPrintTouchPanelFlagSet(MSG_TP_OFF);

	//選択したポケモンのボールナンバーを格納
	parent->SelectBallNo = psel_ptr->FrontBallNo;

	sys_VBlankFuncChange( NULL, NULL );	// VBlankセット

	// カメラ解放
	CamMove_Delete( psel_ptr->CamMovPtr );
	GFC_FreeCamera( psel_ptr->CameraPtr );
	//3Dアニメ解放
	Free3DAnm(psel_ptr);
	//3Dモデル解放
	Free3DObj(psel_ptr);
	//セルアクター破棄
	{
		DelObjRes(&psel_ptr->PokeAct);
		// セルアクターセット解放
		CLACT_DestSet( psel_ptr->PokeAct.ClactSet );
		// セルアクター用リソース管理システム
		CLACT_U_ResManagerDelete( psel_ptr->PokeAct.ResMan[ CLACT_U_CHAR_RES ] );
		CLACT_U_ResManagerDelete( psel_ptr->PokeAct.ResMan[ CLACT_U_PLTT_RES ] );
		CLACT_U_ResManagerDelete( psel_ptr->PokeAct.ResMan[ CLACT_U_CELL_RES ] );
		CLACT_U_ResManagerDelete( psel_ptr->PokeAct.ResMan[ CLACT_U_CELLANM_RES ] );

		//OAMレンダラー破棄
		REND_OAM_Delete();

		DeleteCharManager();
		DeletePlttManager();
	}

	//BMPWin解放
	{
		FreeBmpWin(psel_ptr->MsgWin);
		FreeBmpWin(psel_ptr->GuideWin);
	}
	//BG解放
	{
		GF_BGL_BGControlExit( psel_ptr->bgl, GF_BGL_FRAME1_M );
		GF_BGL_BGControlExit( psel_ptr->bgl, GF_BGL_FRAME2_M );
		GF_BGL_BGControlExit( psel_ptr->bgl, GF_BGL_FRAME0_S );
		GF_BGL_BGControlExit( psel_ptr->bgl, GF_BGL_FRAME1_S );
		GF_BGL_BGControlExit( psel_ptr->bgl, GF_BGL_FRAME2_S );
	}
	//BGL解放
	sys_FreeMemoryEz( psel_ptr->bgl );
	//3Dマネージャ解放
	GF_G3D_Exit( psel_ptr->g3DMan );
	// ワーク解放
	PROC_FreeWork( proc );
	// ヒープ解放
	sys_DeleteHeap( HEAPID_EV_POKESELECT );

	return PROC_RES_FINISH;
}

//----------------------------------------------------------------------------
/**
 *	@brief	OAMリソース破棄
 *
 *	@param	PokeActPtr		リソース管理ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void DelObjRes(POKE_ACT *PokeActPtr)
{
	int i;
	for(i=0;i<BALL_NUM;i++){
		CLACT_U_CharManagerDelete( PokeActPtr->ResObjTbl[i][ CLACT_U_CHAR_RES ] );
		CLACT_U_PlttManagerDelete( PokeActPtr->ResObjTbl[i][ CLACT_U_PLTT_RES ] );
		// リソース破棄
		CLACT_U_ResManagerResDelete(
				PokeActPtr->ResMan[ CLACT_U_CHAR_RES ],
				PokeActPtr->ResObjTbl[i][ CLACT_U_CHAR_RES ] );
		CLACT_U_ResManagerResDelete(
				PokeActPtr->ResMan[ CLACT_U_PLTT_RES ],
				PokeActPtr->ResObjTbl[i][ CLACT_U_PLTT_RES ] );
		CLACT_U_ResManagerResDelete(
				PokeActPtr->ResMan[ CLACT_U_CELL_RES ],
				PokeActPtr->ResObjTbl[i][ CLACT_U_CELL_RES ] );
		CLACT_U_ResManagerResDelete(
				PokeActPtr->ResMan[ CLACT_U_CELLANM_RES ],
				PokeActPtr->ResObjTbl[i][ CLACT_U_CELLANM_RES ] );

		sys_FreeMemoryEz(PokeActPtr->PokeChar[i]);
		sys_FreeMemoryEz(PokeActPtr->PokePal[i]);
	}
}

//----------------------------------------------------------------------------
/**
 *
 *	@brief	VBlank関数
 *
 *	@param	work	ワーク
 *
 *	@return	none
 *
 *
 */
//-----------------------------------------------------------------------------
static void VBlankFunc( void* work )
{
	FPOKE_SEL_WORK* psel_ptr = work;

	// レンダラーOAM転送
	REND_OAMTrans();

	GF_BGL_VBlankFunc( psel_ptr->bgl );

}

//----------------------------------------------------------------------------
/**
 *
 *	@brief	VramBankセットアップ
 *
 *	@param	none
 *
 *	@return	none
 *
 *
 */
//-----------------------------------------------------------------------------
static void SetVramBank( void )
{
	GF_BGL_DISPVRAM vramSetTable = {
		GX_VRAM_BG_80_EF,				// メイン2DエンジンのBG
		GX_VRAM_BGEXTPLTT_NONE,			// メイン2DエンジンのBG拡張パレット
		GX_VRAM_SUB_BG_128_C,			// サブ2DエンジンのBG
		GX_VRAM_SUB_BGEXTPLTT_NONE,		// サブ2DエンジンのBG拡張パレット
		GX_VRAM_OBJ_NONE,				// メイン2DエンジンのOBJ
		GX_VRAM_OBJEXTPLTT_NONE,		// メイン2DエンジンのOBJ拡張パレット
		GX_VRAM_SUB_OBJ_16_I,			// サブ2DエンジンのOBJ
		GX_VRAM_SUB_OBJEXTPLTT_NONE,	// サブ2DエンジンのOBJ拡張パレット
		GX_VRAM_TEX_01_AB,				// テクスチャイメージスロット
		GX_VRAM_TEXPLTT_0_G				// テクスチャパレットスロット
	};
	GF_Disp_SetBank( &vramSetTable );
}

//----------------------------------------------------------------------------
/**
 *
 *	@brief	OAMセットアップ
 *
 *	@param	none
 *
 *	@return	none
 *
 *
 */
//-----------------------------------------------------------------------------
static void SetOAM( const int inHeapID )
{
	// OAMマネージャーの初期化
	NNS_G2dInitOamManagerModule();

	// 共有OAMマネージャ作成
	// レンダラ用OAMマネージャ作成
	// ここで作成したOAMマネージャをみんなで共有する
	REND_OAMInit(
			0, 128,	// メイン画面OAM管理領域
			0, 32,		// メイン画面アフィン管理領域
			0, 128,		// サブ画面OAM管理領域
			0, 32,		// サブ画面アフィン管理領域
			inHeapID);

	// キャラクタマネージャー初期化
	{
		CHAR_MANAGER_MAKE cm = {
			OAM_CHAR_ENTRY_NUM,
			0,0x2800
		};
		cm.heap = inHeapID;

		InitCharManagerReg(&cm, GX_OBJVRAMMODE_CHAR_1D_128K, GX_OBJVRAMMODE_CHAR_1D_32K );
	}
	// パレットマネージャー初期化
	InitPlttManager(OAM_PLTT_ENTRY_NUM, inHeapID);

	// 読み込み開始位置を初期化
	CharLoadStartAll();
	PlttLoadStartAll();
}

//----------------------------------------------------------------------------
/**
 *
 *	@brief	3D面設定
 *
 *	@param	none
 *
 *	@return	none
 *
 *
 */
//-----------------------------------------------------------------------------
static void Setup3D( FPOKE_SEL_WORK *psel_ptr )
{
	int i;
	psel_ptr->g3DMan = GF_G3DMAN_Init(psel_ptr->HeapID,
			GF_G3DMAN_LNK, GF_G3DTEX_256K, GF_G3DMAN_LNK, GF_G3DPLT_64K, NULL );
    G3X_AntiAlias(TRUE);
	G3X_AlphaTest(FALSE, 0);	// アルファテスト　　オフ
	G3X_AlphaBlend(TRUE);		// アルファブレンド　オン

	// エッジマーキング
	G3X_EdgeMarking(TRUE);
	for( i=0; i<8; i++ ){
		psel_ptr->edge_marking[i] = GX_RGB( 4, 4, 4 );
	}
	G3X_SetEdgeColorTable( psel_ptr->edge_marking );

	// クリアカラーの設定
    G3X_SetClearColor(GX_RGB(31, 31, 16),	// clear color
                      0,				// clear alpha
                      0x7fff,			// clear depth
                      63,				// clear polygon ID
                      FALSE				// fog
                      );

	// ライトとアンビエント
	NNS_G3dGlbLightVector( 0, 0, -FX32_ONE, 0 );
	NNS_G3dGlbLightColor( 0, GX_RGB( 31,31,31 ) );
	NNS_G3dGlbMaterialColorDiffAmb( GX_RGB( 31,31,31 ), GX_RGB( 31,31,31 ), FALSE );
	NNS_G3dGlbMaterialColorSpecEmi( GX_RGB( 31,31,31 ), GX_RGB( 31,31,31 ), FALSE );
}

static void Draw(FPOKE_SEL_WORK *psel_ptr)
{

	//セルアクター描画
	CLACT_Draw( psel_ptr->PokeAct.ClactSet );
	//３Ｄ描画開始
	GF_G3X_Reset();


	NNS_G3dGePushMtx();
	{
		// カメラ設定
		GFC_CameraLookAt();

		//　モデルの描画
		Draw3D(psel_ptr);
	}
	NNS_G3dGePopMtx(1);


	/* ジオメトリ＆レンダリングエンジン関連メモリのスワップ */
	GF_G3_RequestSwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_Z);

	// セルアクター描画
///	CLACT_Draw( p_psl->clact_set );
}

//----------------------------------------------------------------------------
/**
 *	@brief	3Dオブジェクト描画処理
 *
 *	@param	p_psl
 *
 *	@return
 */
//-----------------------------------------------------------------------------
static void Draw3D( FPOKE_SEL_WORK *psel_ptr )
{
	int i;
	OBJ_3D_DATA *data;
/**
	// ライトとアンビエント
	NNS_G3dGlbLightVector( 0, 0, -FX32_ONE, 0 );
	NNS_G3dGlbLightColor( 0, GX_RGB( 31,31,31 ) );
	NNS_G3dGlbMaterialColorDiffAmb( GX_RGB( 31,31,31 ), GX_RGB( 31,31,31 ), FALSE );
	NNS_G3dGlbMaterialColorSpecEmi( GX_RGB( 31,31,31 ), GX_RGB( 31,31,31 ), FALSE );
*/
	VecFx32 scale = {FX32_ONE,FX32_ONE,FX32_ONE};

	for( i=0; i<POKESELECT_TURN_TABLE; i++ ){
		MtxFx33 mtx;
		MtxFx33 calc_mtx;

		data = &psel_ptr->ObjData[i];

		if( data->DrawFlag ){
			// 回転行列作成
			MTX_Identity33( &mtx );
			MTX_RotY33( &calc_mtx, FX_SinIdx( data->RotY ), FX_CosIdx( data->RotY ) );
			MTX_Concat33( &calc_mtx, &mtx, &mtx );
			simple_3DModelDraw( &data->RenderObj, &data->Trans, &mtx, &scale );
		}
	}

	//ベース
	{
		MtxFx33 mtx;
		VecFx32 trans = {0,0,0};
		VecFx32 scale = {FX32_ONE,FX32_ONE,FX32_ONE};
		u16 rot;

		// 位置設定
		NNS_G3dGlbSetBaseTrans(&trans);
		// 角度設定
		rot = psel_ptr->NowRot;
		MTX_Identity33( &mtx );
		MTX_RotY33( &mtx, FX_SinIdx(rot), FX_CosIdx(rot) );
		NNS_G3dGlbSetBaseRot(&mtx);
		// スケール設定
		NNS_G3dGlbSetBaseScale(&scale);

		NNS_G3dGlbFlush();

	}

	//ボール描画
	for(i=POKESELECT_TURN_TABLE;i<POKESELECT_BALL1+BALL_NUM;i++){
		data = &psel_ptr->ObjData[i];
		if( data->DrawFlag ){
			NNS_G3dGePushMtx();
			DrawObj( data );
			NNS_G3dGePopMtx(1);
			NNS_G3dGlbFlush();
		}
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	BG面設定
 *
 *	@param	bgl			BGL
 *	@param	inHeapID	ヒープID
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetupBG( GF_BGL_INI* bgl, const int inHeapID )
{
	// BG0の優先順位
	G2_SetBG0Priority( 2 );

	// メイン画面 BG1面		文字列書き込み面
	{
		GF_BGL_BGCNT_HEADER bg_cnt_header = {
			0, 0, 0x800, 0,
			GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
			GX_BG_SCRBASE_0x0000, GX_BG_CHARBASE_0x04000,
			GX_BG_EXTPLTT_01, 0, 0, 0, FALSE
		};
		GF_BGL_BGControlSet( bgl, GF_BGL_FRAME1_M, &bg_cnt_header, GF_BGL_MODE_TEXT );
		GF_BGL_ClearCharSet( GF_BGL_FRAME1_M, 32, 0, inHeapID );
		GF_BGL_ScrClear( bgl, GF_BGL_FRAME1_M );
	}
	// メイン画面 BG2面		フォントプレート面
	{
		GF_BGL_BGCNT_HEADER bg_cnt_header = {
			0, 0, 0x800, 0,
			GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
			GX_BG_SCRBASE_0x0800, GX_BG_CHARBASE_0x0c000,
			GX_BG_EXTPLTT_01, 1, 0, 0, FALSE
		};
		GF_BGL_BGControlSet( bgl, GF_BGL_FRAME2_M, &bg_cnt_header, GF_BGL_MODE_TEXT );
		GF_BGL_ClearCharSet( GF_BGL_FRAME2_M, 32, 0, inHeapID );
		GF_BGL_ScrClear( bgl, GF_BGL_FRAME2_M );
	}

	// サブ画面 BG0面		文字面
	{
		GF_BGL_BGCNT_HEADER bg_cnt_header = {
			0, 0, 0x800, 0,
			GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
			GX_BG_SCRBASE_0x1000, GX_BG_CHARBASE_0x14000,
			GX_BG_EXTPLTT_01, 0, 0, 0, FALSE
		};
		GF_BGL_BGControlSet( bgl, GF_BGL_FRAME0_S, &bg_cnt_header, GF_BGL_MODE_TEXT );
		GF_BGL_ClearCharSet( GF_BGL_FRAME0_S, 32, 0, inHeapID );
		GF_BGL_ScrClear( bgl, GF_BGL_FRAME0_S );
	}

	// サブ画面 BG1面		ボール内部面
	{
		GF_BGL_BGCNT_HEADER bg_cnt_header = {
			0, 0, 0x800, 0,
			GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
			GX_BG_SCRBASE_0x0000, GX_BG_CHARBASE_0x10000,
			GX_BG_EXTPLTT_01, 2, 0, 0, FALSE
		};
		GF_BGL_BGControlSet( bgl, GF_BGL_FRAME1_S, &bg_cnt_header, GF_BGL_MODE_TEXT );
		GF_BGL_ClearCharSet( GF_BGL_FRAME1_S, 32, 0, inHeapID );
		GF_BGL_ScrClear( bgl, GF_BGL_FRAME1_S );
	}

	// サブ画面 BG2面		スポット
	{
		GF_BGL_BGCNT_HEADER bg_cnt_header = {
			0, 0, 0x800, 0,
			GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
			GX_BG_SCRBASE_0x0800, GX_BG_CHARBASE_0x0c000,
			GX_BG_EXTPLTT_01, 1, 0, 0, FALSE
		};
		GF_BGL_BGControlSet( bgl, GF_BGL_FRAME2_S, &bg_cnt_header, GF_BGL_MODE_TEXT );
		GF_BGL_ClearCharSet( GF_BGL_FRAME2_S, 32, 0, inHeapID );
		GF_BGL_ScrClear( bgl, GF_BGL_FRAME2_S );
	}

}

//----------------------------------------------------------------------------
/**
 *	@brief	カメラ作成＆初期化
 *
 *	@param	p_psl		ワーク
 *	@param	heap		ヒープ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void InitCamera( FPOKE_SEL_WORK *psel_ptr )
{
	// 初期化
	{
		CAMERA_ANGLE angle;
		VecFx32 up;
		VecFx32 shift_vec = { 0, CAMERA_SHIFT_Y, CAMERA_SHIFT_Z };

		psel_ptr->CameraTarget.x = CAMERA_TARGET_X;
		psel_ptr->CameraTarget.y = CAMERA_TARGET_Y;
		psel_ptr->CameraTarget.z = CAMERA_TARGET_Z;

		angle.x = CAMERA_ANGLE_X;
		angle.y = CAMERA_ANGLE_Y;
		angle.z = CAMERA_ANGLE_Z;


		GFC_InitCameraTDA(
				&psel_ptr->CameraTarget, CAMERA_DISTANCE,
				&angle, CAMERA_PERS,
				GF_CAMERA_PERSPECTIV,
				TRUE,
				psel_ptr->CameraPtr
				);
		GFC_ShiftCamera(&shift_vec, psel_ptr->CameraPtr);
		GFC_SetCameraClip(4*FX32_ONE,256*FX32_ONE, psel_ptr->CameraPtr);

		up.x = 0;
		up.y = FX32_ONE;
		up.z = 0;
		GFC_SetCamUp( &up, psel_ptr->CameraPtr );

		GFC_AttachCamera( psel_ptr->CameraPtr );
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	セルアクター初期化
 *
 *	@param	p_psl		ワーク
 *	@param	heap		ヒープ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void InitClact( FPOKE_SEL_WORK *psel_ptr )
{
	POKE_ACT *poke_act;

	poke_act = &psel_ptr->PokeAct;
	// セルアクターセット
	poke_act->ClactSet = CLACT_U_SetEasyInit( CLACT_SET_WORK_NUM, &poke_act->RendData, psel_ptr->HeapID );

	// セルアクター用リソース管理システム
	poke_act->ResMan[ CLACT_U_CHAR_RES ] = CLACT_U_ResManagerInit( CLACT_RES_DATA_TBL_NUM, CLACT_U_CHAR_RES, psel_ptr->HeapID );
	poke_act->ResMan[ CLACT_U_PLTT_RES ] = CLACT_U_ResManagerInit( CLACT_RES_DATA_TBL_NUM, CLACT_U_PLTT_RES, psel_ptr->HeapID );
	poke_act->ResMan[ CLACT_U_CELL_RES ] = CLACT_U_ResManagerInit( CLACT_RES_DATA_TBL_NUM, CLACT_U_CELL_RES, psel_ptr->HeapID );
	poke_act->ResMan[ CLACT_U_CELLANM_RES ] = CLACT_U_ResManagerInit( CLACT_RES_DATA_TBL_NUM, CLACT_U_CELLANM_RES, psel_ptr->HeapID );

	// OBJON
	GF_Disp_GXS_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );
}


//----------------------------------------------------------------------------
/**
 *	@brief	3Dオブジェを作成する
 *
 *	@param	psel_ptr	ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void Create3DObj( FPOKE_SEL_WORK *psel_ptr )
{
	int i;
/**
	//ボールエフェクトモデル
	Load3DObj( &psel_ptr->ObjData[ POKESELECT_BALL_EF ], NARC_first_poke_select_tt_ball_ef_nsbmd,
			psel_ptr->HeapID );
	//トランス
	Set3DObjTrans(&psel_ptr->ObjData[ POKESELECT_BALL_EF ],0,BALL_OFS,TURN_TABLE_R);
	//スケール
	Set3DObjScale(&psel_ptr->ObjData[ POKESELECT_BALL_EF ],FX32_ONE, FX32_ONE, FX32_ONE);

	//台
	Load3DObj( &psel_ptr->ObjData[ POKESELECT_TABLE ], NARC_first_poke_select_tt_tabletop_nsbmd,
			psel_ptr->HeapID );
	//トランス
	Set3DObjTrans(&psel_ptr->ObjData[ POKESELECT_TABLE ],0,0,0);
	//スケール
	Set3DObjScale(&psel_ptr->ObjData[ POKESELECT_TABLE ],FX32_ONE, FX32_ONE, FX32_ONE);

	//ターンテーブル
	Load3DObj( &psel_ptr->ObjData[ POKESELECT_TURN_TABLE ], NARC_first_poke_select_tt_turntable_nsbmd,
			psel_ptr->HeapID );
	//トランス
	Set3DObjTrans(&psel_ptr->ObjData[ POKESELECT_TURN_TABLE ],0,0,0);
	//スケール
	Set3DObjScale(&psel_ptr->ObjData[ POKESELECT_TURN_TABLE ],FX32_ONE, FX32_ONE, FX32_ONE);

	//ボール
	for(i=0;i<BALL_NUM;i++){
		Load3DObj( &psel_ptr->ObjData[ POKESELECT_BALL1+i ], NARC_first_poke_select_tt_ball_nsbmd,
				psel_ptr->HeapID );
	}
*/

	//ボールエフェクトモデル
	Load3DObj( &psel_ptr->ResData[ RES_BALL_EF ], NARC_first_poke_select_tt_ball_ef_nsbmd,
			psel_ptr->HeapID );
	//トランス
	Set3DObjTrans(&psel_ptr->ObjData[ POKESELECT_BALL_EF ],0,BALL_OFS,TURN_TABLE_R);
	//スケール
	Set3DObjScale(&psel_ptr->ObjData[ POKESELECT_BALL_EF ],FX32_ONE, FX32_ONE, FX32_ONE);

	//台
	Load3DObj( &psel_ptr->ResData[ RES_TABLE ], NARC_first_poke_select_tt_tabletop_nsbmd,
			psel_ptr->HeapID );
	//トランス
	Set3DObjTrans(&psel_ptr->ObjData[ POKESELECT_TABLE ],0,0,0);
	//スケール
	Set3DObjScale(&psel_ptr->ObjData[ POKESELECT_TABLE ],FX32_ONE, FX32_ONE, FX32_ONE);

	//ターンテーブル
	Load3DObj( &psel_ptr->ResData[ RES_TURN_TABLE ], NARC_first_poke_select_tt_turntable_nsbmd,
			psel_ptr->HeapID );
	//トランス
	Set3DObjTrans(&psel_ptr->ObjData[ POKESELECT_TURN_TABLE ],0,0,0);
	//スケール
	Set3DObjScale(&psel_ptr->ObjData[ POKESELECT_TURN_TABLE ],FX32_ONE, FX32_ONE, FX32_ONE);

	//ボール
	Load3DObj( &psel_ptr->ResData[ RES_BALL ], NARC_first_poke_select_tt_ball_nsbmd,
				psel_ptr->HeapID );

	//OBJ作成
	//ボールエフェクトモデル
	Make3DObj( &psel_ptr->ObjData[ POKESELECT_BALL_EF ], &psel_ptr->ResData[ RES_BALL_EF ]);
	//台
	Make3DObj( &psel_ptr->ObjData[ POKESELECT_TABLE ], &psel_ptr->ResData[ RES_TABLE ]);
	//ターンテーブル
	Make3DObj( &psel_ptr->ObjData[ POKESELECT_TURN_TABLE ], &psel_ptr->ResData[ RES_TURN_TABLE ]);
	//ボール
	for(i=0;i<BALL_NUM;i++){
		Make3DObj( &psel_ptr->ObjData[ POKESELECT_BALL1+i ], &psel_ptr->ResData[ RES_BALL ]);
	}

	psel_ptr->ObjData[ POKESELECT_BALL_EF ].DrawFlag = FALSE;
	psel_ptr->ObjData[ POKESELECT_TURN_TABLE ].DrawFlag = TRUE;
	psel_ptr->ObjData[ POKESELECT_TABLE ].DrawFlag = TRUE;
	psel_ptr->ObjData[ POKESELECT_BALL1 ].DrawFlag = TRUE;
	psel_ptr->ObjData[ POKESELECT_BALL2 ].DrawFlag = TRUE;
	psel_ptr->ObjData[ POKESELECT_BALL3 ].DrawFlag = TRUE;


	//アニメ関連
	Load3DObjAnm( NARC_first_poke_select_tt_turntable_nsbta, psel_ptr->HeapID,
				  &psel_ptr->Allocator,
				  &psel_ptr->ResData[RES_TURN_TABLE], &psel_ptr->AnmData[ANM_TURN_TABLE]  );
	Load3DObjAnm( NARC_first_poke_select_ball_rock_nsbca, psel_ptr->HeapID,
				  &psel_ptr->Allocator,
				  &psel_ptr->ResData[RES_BALL], &psel_ptr->AnmData[ANM_BALL_MOVE1]  );
	Load3DObjAnm( NARC_first_poke_select_ball_rock_nsbca, psel_ptr->HeapID,
				  &psel_ptr->Allocator,
				  &psel_ptr->ResData[RES_BALL], &psel_ptr->AnmData[ANM_BALL_MOVE2]  );
	Load3DObjAnm( NARC_first_poke_select_ball_rock_nsbca, psel_ptr->HeapID,
				  &psel_ptr->Allocator,
				  &psel_ptr->ResData[RES_BALL], &psel_ptr->AnmData[ANM_BALL_MOVE3]  );

	Load3DObjAnm( NARC_first_poke_select_tt_ball_nsbca, psel_ptr->HeapID,
				  &psel_ptr->Allocator,
				  &psel_ptr->ResData[RES_BALL], &psel_ptr->AnmData[ANM_BALL_OPEN]  );

	Load3DObjAnm( NARC_first_poke_select_tt_ball_ef_nsbca, psel_ptr->HeapID,
				  &psel_ptr->Allocator,
				  &psel_ptr->ResData[RES_BALL_EF], &psel_ptr->AnmData[ANM_BALL_EF]  );

	//ターンテーブルアニメセット
	Add3DAnm(&psel_ptr->ObjData[ POKESELECT_TURN_TABLE ], &psel_ptr->AnmData[ANM_TURN_TABLE]);

	//ボールアニメをセット
	Add3DAnm(&psel_ptr->ObjData[ POKESELECT_BALL1 ], &psel_ptr->AnmData[ANM_BALL_MOVE1]);
	Add3DAnm(&psel_ptr->ObjData[ POKESELECT_BALL2 ], &psel_ptr->AnmData[ANM_BALL_MOVE2]);
	Add3DAnm(&psel_ptr->ObjData[ POKESELECT_BALL3 ], &psel_ptr->AnmData[ANM_BALL_MOVE3]);
}

//----------------------------------------------------------------------------
/**
 *	@brief	3Dアニメを解放する
 *
 *	@param	psel_ptr	ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void Free3DAnm(FPOKE_SEL_WORK *psel_ptr)
{
	int i;
	for( i=0;i<ANM_NUM;i++ ){
		Delete3DAnm( &psel_ptr->AnmData[i], &psel_ptr->Allocator );
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	3Dオブジェを解放する
 *
 *	@param	psel_ptr	ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void Free3DObj(FPOKE_SEL_WORK *psel_ptr)
{
	int i;
	for( i=0;i<RES_3DOBJ_NUM;i++ ){
		Delete3DObj( &psel_ptr->ResData[i] );
	}
}

// モデルﾃﾞｰﾀ読み込み＆設定
static void Load3DObj( RES_DATA * pResData, const int inMdlDataIdx, const int inHeapID )
{
	// モデルﾃﾞｰﾀ読み込み
	pResData->pResMdl = ArcUtil_Load( ARC_FIRST_POKE_SELECT, inMdlDataIdx, FALSE, inHeapID, ALLOC_TOP );

	// モデルﾃﾞｰﾀ取得
	pResData->pModelSet	= NNS_G3dGetMdlSet( pResData->pResMdl );
	pResData->pModel	= NNS_G3dGetMdlByIdx( pResData->pModelSet, 0 );
	pResData->pMdlTex	= NNS_G3dGetTex( pResData->pResMdl );

	// モデルﾃﾞｰﾀを転送
	LoadVRAMTexture( pResData->pMdlTex );

}

//3DOBJのテクスチャバインドと初期化
static void Make3DObj( OBJ_3D_DATA* pObjData, RES_DATA *pRes)
{
	BindTexture( pRes->pResMdl, pRes->pMdlTex );
	// レンダーオブジェクトに登録
	NNS_G3dRenderObjInit( &pObjData->RenderObj, pRes->pModel );
}

// アニメﾃﾞｰﾀ読み込み
static void Load3DObjAnm( const int inMdlDataIdx, const int inHeapID,
						  NNSFndAllocator* pAllocator,
						  RES_DATA* inResDataPtr, ANM_DATA* outAnmData )
{
	void *pOneResAnm;		// 1つ切り取ったリソース
	// アニメﾃﾞｰﾀ読み込み
	outAnmData->ResAnmPtr = ArcUtil_Load( ARC_FIRST_POKE_SELECT, inMdlDataIdx, FALSE, inHeapID, ALLOC_TOP );

	//リソース取得
	pOneResAnm = NNS_G3dGetAnmByIdx(outAnmData->ResAnmPtr,0);

	// アニメオブジェのメモリ確保
	outAnmData->AnmObjPtr = NNS_G3dAllocAnmObj(
			pAllocator,
			pOneResAnm,
			inResDataPtr->pModel );

	// アニメオブジェ初期化
	NNS_G3dAnmObjInit(
		outAnmData->AnmObjPtr,
		pOneResAnm,
		inResDataPtr->pModel,
		inResDataPtr->pMdlTex );

	// レンダーオブジェクトに登録
///	NNS_G3dRenderObjAddAnmObj( &pObjData->RenderObj, pObjData->pAnmObj );
}

//アニメ適用
static void Add3DAnm(OBJ_3D_DATA* pObjData, ANM_DATA* pAnmData)
{
	NNS_G3dRenderObjAddAnmObj( &pObjData->RenderObj, pAnmData->AnmObjPtr );
}

//アニメ切り離し
static void Remove3DAnm(OBJ_3D_DATA* pObjData, ANM_DATA* pAnmData)
{
	NNS_G3dRenderObjRemoveAnmObj( &pObjData->RenderObj, pAnmData->AnmObjPtr );
}

static BOOL Play3DAnm(ANM_DATA* pAnmData)
{
	BOOL rc = FALSE;
	if (pAnmData->AnmObjPtr->frame+(FX32_ONE) != NNS_G3dAnmObjGetNumFrame(pAnmData->AnmObjPtr)){
		pAnmData->AnmObjPtr->frame += (FX32_ONE);
	}else{
		rc = TRUE;
	}
	return rc;
}

static void Play3DAnmLoop(ANM_DATA* pAnmData, const ZOOM_STATE inZoomState)
{
	pAnmData->AnmObjPtr->frame += (FX32_ONE);
	if (inZoomState == ZOOM_ST_UP){
		if ( pAnmData->AnmObjPtr->frame == RIGHT_LARGE_SWAY_START_FRAME ){
			pAnmData->AnmObjPtr->frame = LEFT_SMALL_SWAY_START_FRAME;
		}
	}

	if (pAnmData->AnmObjPtr->frame >= NNS_G3dAnmObjGetNumFrame(pAnmData->AnmObjPtr)){
		if (inZoomState == ZOOM_ST_UP){
			//小刻みの部分でループ
			pAnmData->AnmObjPtr->frame = LEFT_SMALL_SWAY_START_FRAME;
		}else{
			pAnmData->AnmObjPtr->frame = 0;
		}
	}
}

static void SwayBall(FPOKE_SEL_WORK *psel_ptr)
{
	u8 anm1 = ANM_BALL_MOVE1 + psel_ptr->FrontBallNo;
	u8 anm2 = ANM_BALL_MOVE1 + (psel_ptr->FrontBallNo+1)%BALL_NUM;
	u8 anm3 = ANM_BALL_MOVE1 + (psel_ptr->FrontBallNo+2)%BALL_NUM;
	Play3DAnmLoop(&psel_ptr->AnmData[anm1], psel_ptr->Zoom);
	psel_ptr->AnmData[anm2].AnmObjPtr->frame = 0;
	psel_ptr->AnmData[anm3].AnmObjPtr->frame = 0;
}

static BOOL CheckSmallSwayFrame(FPOKE_SEL_WORK *psel_ptr)
{
	u8 anm = ANM_BALL_MOVE1 + psel_ptr->FrontBallNo;
	if ( psel_ptr->AnmData[anm].AnmObjPtr->frame >= LEFT_SMALL_SWAY_START_FRAME ){
		return TRUE;
	}else{
		return FALSE;
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	3Dオブジェクトの破棄
 *
 *	@param	pObjData	オブジェクト
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void Delete3DObj( RES_DATA* pResData )
{
	// 全リソース破棄
	if(pResData->pResMdl){
		sys_FreeMemoryEz( pResData->pResMdl );
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	3Dアニメの破棄
 *
 *	@param	pObjData	オブジェクト
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void Delete3DAnm( ANM_DATA* pAnmData, NNSFndAllocator* pAllocator )
{
	//アニメ破棄
	if (pAnmData->ResAnmPtr){
		NNS_G3dFreeAnmObj( pAllocator, pAnmData->AnmObjPtr );
		sys_FreeMemoryEz( pAnmData->ResAnmPtr );
	}
}


//----------------------------------------------------------------------------
/**
 *	@brief	3Dobj座標セット
 *
 *	@param	pObjData	3DOBJポインタ
 *	@param	inX			X座標
 *	@param	inY			Y座標
 *	@param	inZ			Z座標
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void Set3DObjTrans(OBJ_3D_DATA* pObjData,
				const fx32 inX, const fx32 inY, const fx32 inZ )
{
	pObjData->Trans.x = inX;
	pObjData->Trans.y = inY;
	pObjData->Trans.z = inZ;
}

//----------------------------------------------------------------------------
/**
 *	@brief	3Dobjスケールセット
 *
 *	@param	pObjData	3DOBJポインタ
 *	@param	inX			X
 *	@param	inY			Y
 *	@param	inZ			Z
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void Set3DObjScale(OBJ_3D_DATA* pObjData,
				const fx32 inX, const fx32 inY, const fx32 inZ )
{
	pObjData->Scal.x = inX;
	pObjData->Scal.y = inY;
	pObjData->Scal.z = inZ;
}


static void SetBallPos(FPOKE_SEL_WORK *psel_ptr)
{
	int i;
	u8 no;
	VecFx32 vec;
	VecFx32 base = {0,BALL_OFS,TURN_TABLE_R};

	//手前のボールナンバー取得
	no = psel_ptr->FrontBallNo;

	for(i=0;i<BALL_NUM;i++){
		MtxFx33 mtx;
		u16 rot = (0x10000*i) / 3;
		MTX_RotY33(&mtx, FX_SinIdx(rot), FX_CosIdx(rot));
		MTX_MultVec33(&base, &mtx, &vec);
		psel_ptr->BallPos[no] = vec;
		psel_ptr->BallPos[no].y += BALL_R;
		//トランス
		Set3DObjTrans(&psel_ptr->ObjData[POKESELECT_BALL1+no],
				vec.x, vec.y, vec.z );
		//スケール
		Set3DObjScale(&psel_ptr->ObjData[POKESELECT_BALL1+no],
				FX32_ONE, FX32_ONE, FX32_ONE);
		//ローテーション
		psel_ptr->ObjData[POKESELECT_BALL1+no].RotY = rot;
		psel_ptr->ObjData[POKESELECT_BALL1+no].RotX = 0;

		OS_Printf("BallNo：%d\n",no);

		no = (no+1)%BALL_NUM;
	}
}

static void DrawObj( OBJ_3D_DATA *data)
{
	MtxFx43 mtx;
	GetTRSMatrix( data, &mtx );

	NNS_G3dGeMultMtx43(&mtx);

	NNS_G3dDraw(&data->RenderObj);
}

static void GetTRSMatrix( OBJ_3D_DATA *data, MtxFx43 *outMtx )
{
	MtxFx43	rot;
	MtxFx43 scl;
	MTX_Identity43(outMtx);
	MTX_TransApply43( outMtx, outMtx, data->Trans.x, data->Trans.y, data->Trans.z);
	{
		MtxFx43	calc;
		MTX_Identity43( &rot );
		MTX_RotX43( &calc, FX_SinIdx( data->RotX ), FX_CosIdx( data->RotX ) );
		MTX_Concat43( &calc, &rot, &rot );

		MTX_RotY43( &calc, FX_SinIdx( data->RotY ), FX_CosIdx( data->RotY ) );
		MTX_Concat43( &calc, &rot, &rot );
	}

	MTX_Scale43(&scl,data->Scal.x, data->Scal.y, data->Scal.z);

	MTX_Concat43(&rot, outMtx, outMtx);
	MTX_Concat43(&scl, outMtx, outMtx);
}

//回転値の加減算
static BOOL AddRot(FPOKE_SEL_WORK *psel_ptr, const s16 inRot)
{
	BOOL rc;

	rc = FALSE;
	//現在値に加算
	psel_ptr->NowRot += inRot;

	if (inRot>=0){	//入力が＋の場合(反時計回り)
		if (psel_ptr->NowRot >= 0x10000/3){
			//回転終了
			psel_ptr->NowRot = 0;
			psel_ptr->AddRot = 0;
			//ボール再配置
			ResetBallPos(psel_ptr, REV_PLUS);
			rc = TRUE;
		}
	}else{			//入力が-の場合(時計回り)
		if (psel_ptr->NowRot <= -0x10000/3){
			//回転終了
			psel_ptr->NowRot = 0;
			psel_ptr->AddRot = 0;
			//ボール再配置
			ResetBallPos(psel_ptr, REV_MINUS);
			rc = TRUE;
		}
	}

	return rc;
}

//回転後の再設定
static void ResetBallPos(FPOKE_SEL_WORK *psel_ptr, const REV_DIR inRevDir)
{
	//手前にあるボールのナンバーを更新
	if (inRevDir == REV_MINUS){
		//時計周り
		psel_ptr->FrontBallNo = (psel_ptr->FrontBallNo+1)%BALL_NUM;
	}else if (inRevDir == REV_PLUS){
		s8 val;
		//反時計回り
		val = psel_ptr->FrontBallNo-1;
		if (val<0){
			val = BALL_NUM-1;
		}
		psel_ptr->FrontBallNo = val;
	}
	SetBallPos(psel_ptr);
}


//----------------------------------------------------------------------------
/**
 *	@brief	ビットマップウィンドウ作成
 *
 *	@param	psel_ptr	ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void MakeBmpWin( FPOKE_SEL_WORK *psel_ptr )
{
	psel_ptr->MsgWin = GF_BGL_BmpWinAllocGet( psel_ptr->HeapID, 1 );
	psel_ptr->GuideWin = GF_BGL_BmpWinAllocGet( psel_ptr->HeapID, 1 );

	// ビットマップウィンドウ登録
	GF_BGL_BmpWinAdd( psel_ptr->bgl, psel_ptr->MsgWin,
			GF_BGL_FRAME0_S, BG_FONTBMP_X, BG_FONTBMP_Y, BG_FONTBMP_CX, BG_FONTBMP_CY, BG_FONT_STR_COLOR, TALK_WIN_CGX_SIZ + 1 );
	GF_BGL_BmpWinAdd( psel_ptr->bgl, psel_ptr->GuideWin,
			GF_BGL_FRAME1_M, BG_GUIDEBMP_X, BG_GUIDEBMP_Y, BG_GUIDEBMP_CX, BG_GUIDEBMP_CY, BG_FONT_STR_COLOR, TALK_WIN_CGX_SIZ + 1 );

	// クリーン
	GF_BGL_BmpWinDataFill( psel_ptr->MsgWin, 15 );
	GF_BGL_BmpWinDataFill( psel_ptr->GuideWin, 0 );

	// 枠を描画
	TalkWinGraphicSet( psel_ptr->bgl, GF_BGL_FRAME0_S, BG_FONT_CG_OFS, BG_FONT_COLOR, psel_ptr->WinType, psel_ptr->HeapID );

	// 会話フォントパレット読み込み
	ArcUtil_PalSet( ARC_FIRST_POKE_SELECT, NARC_first_poke_select_font_talk_NCLR, PALTYPE_SUB_BG, BG_FONT_STR_COLOR * 32, 32, psel_ptr->HeapID );
	ArcUtil_PalSet( ARC_FIRST_POKE_SELECT, NARC_first_poke_select_font_talk_NCLR, PALTYPE_MAIN_BG, BG_FONT_STR_COLOR * 32, 32, psel_ptr->HeapID );

	BmpTalkWinWrite( psel_ptr->MsgWin, WINDOW_TRANS_ON, BG_FONT_CG_OFS, BG_FONT_COLOR );
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	BGロード
 *
 * @param	bgl			BGL
 * @param	inHeapID	ヒープID
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void LoadBG(GF_BGL_INI * bgl, const int inHeapID)
{
	//メインキャラ
	ArcUtil_BgCharSet(ARC_FIRST_POKE_SELECT, NARC_first_poke_select_ball_in_win_NCGR,
						bgl, GF_BGL_FRAME2_M, 0, 0, FALSE, inHeapID);
	//サブキャラ
	ArcUtil_BgCharSet(ARC_FIRST_POKE_SELECT, NARC_first_poke_select_ball_inner_cmp_NCGR,
						bgl, GF_BGL_FRAME1_S, 0, 0, FALSE, inHeapID);
	ArcUtil_BgCharSet(ARC_FIRST_POKE_SELECT, NARC_first_poke_select_inner_circle_cmp_NCGR,
						bgl, GF_BGL_FRAME2_S, 0, 0, FALSE, inHeapID);
	//メインスクリーン
	ArcUtil_ScrnSet(ARC_FIRST_POKE_SELECT, NARC_first_poke_select_ball_in_win_NSCR,
						bgl, GF_BGL_FRAME2_M, 0, 0, FALSE, inHeapID);
	//サブスクリーン
	ArcUtil_ScrnSet(ARC_FIRST_POKE_SELECT, NARC_first_poke_select_ball_inner_cmp_NSCR,
						bgl, GF_BGL_FRAME1_S, 0, 0, FALSE, inHeapID);
	ArcUtil_ScrnSet(ARC_FIRST_POKE_SELECT, NARC_first_poke_select_inner_circle_cmp_NSCR,
						bgl, GF_BGL_FRAME2_S, 0, 0, FALSE, inHeapID);
	//メインパレット
	ArcUtil_PalSet( ARC_FIRST_POKE_SELECT, NARC_first_poke_select_ball_in_win_NCLR,
						PALTYPE_MAIN_BG, BG_PAL_OFS * 32, 32, inHeapID );
	//サブパレット
	ArcUtil_PalSet( ARC_FIRST_POKE_SELECT, NARC_first_poke_select_ball_inner_NCLR,
						PALTYPE_SUB_BG, BG_PAL_OFS * 32, 32, inHeapID );
	ArcUtil_PalSet( ARC_FIRST_POKE_SELECT, NARC_first_poke_select_inner_circle_NCLR,
						PALTYPE_SUB_BG, (BG_PAL_OFS+1) * 32, 32, inHeapID );
	//スクリーンパレット変更
	GF_BGL_ScrPalChange( bgl, GF_BGL_FRAME2_M, 0, 0, 32, 24, BG_PAL_OFS );
	GF_BGL_ScrPalChange( bgl, GF_BGL_FRAME1_S, 0, 0, 32, 24, BG_PAL_OFS );
	GF_BGL_ScrPalChange( bgl, GF_BGL_FRAME2_S, 0, 0, 32, 24, BG_PAL_OFS+1 );
	GF_BGL_LoadScreenReq( bgl, GF_BGL_FRAME2_M );
	GF_BGL_LoadScreenReq( bgl, GF_BGL_FRAME1_S );
	GF_BGL_LoadScreenReq( bgl, GF_BGL_FRAME2_S );

	//アルファセット
	G2S_SetBlendAlpha( GX_BLEND_PLANEMASK_BG2,
			GX_BLEND_PLANEMASK_BG1|GX_BLEND_PLANEMASK_BD, 16-ALPHA_VAL, ALPHA_VAL );
}

//----------------------------------------------------------------------------
/**
 *	@brief	ウエイト文字列描画用　関数　STRBUF保存
 *
 *	@param	pBmp		ビットマップ
 *	@param	inHeapID	ヒープ
 *	@param	inWindow	枠の有無
 *	@param	inArcIdx	アーカイブIDX
 *	@param	inMsgIdx	メッセージIDX
 *	@param	inColor		カラー
 *	@param	inWait		ウエイト
 *	@param	ppStrBuf	文字列バッファポインタ格納先
 *
 *	@return	メッセージインデックス
 */
//-----------------------------------------------------------------------------
static u8 PrintMsg( GF_BGL_BMPWIN* pBmp, const int inHeapID, const BOOL inWindow,
					const int inArcIdx, const int inMsgIdx, const GF_PRINTCOLOR inColor,
					const u32 inWait, STRBUF** ppStrBuf )
{
	MSGDATA_MANAGER* msg_data;
	u8 msg_index;

	GF_ASSERT( (*ppStrBuf) == NULL );

	// 文字列取得
	msg_data = MSGMAN_Create( MSGMAN_TYPE_NORMAL, ARC_MSG, inArcIdx, inHeapID );
	GF_ASSERT( msg_data );
	*ppStrBuf = MSGMAN_AllocString( msg_data, inMsgIdx );

	// ビットマップ初期化(背景色でフィル)
	GF_BGL_BmpWinDataFill( pBmp, GF_PRINTCOLOR_GET_GROUND(inColor) );

	// 文字列書き込み
	msg_index = GF_STR_PrintColor( pBmp, FONT_TALK, *ppStrBuf, 0, 0, inWait, inColor, NULL );

	if (inWindow){
		BmpTalkWinWrite( pBmp, WINDOW_TRANS_ON, BG_FONT_CG_OFS, BG_FONT_COLOR );
	}else{
		GF_BGL_BmpWinOn( pBmp );
	}
	MSGMAN_Delete( msg_data );

	return msg_index;
}

//----------------------------------------------------------------------------
/**
 *	@brief	メイン画面メッセージ表示
 *
 *	@param	psel_ptr	ワーク
 *	@param	inMsgIdx	メッセージIDX
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void PrintMainDispMsg(FPOKE_SEL_WORK *psel_ptr, const int inMsgIdx)
{
	STRBUF* strbuf = NULL;
	PrintMsg( psel_ptr->GuideWin, psel_ptr->HeapID, FALSE,
				NARC_msg_ev_pokeselect_dat, inMsgIdx, BG_FONTBMP_PRICOLOR2, MSG_ALLPUT, &strbuf );
	STRBUF_Delete( strbuf );
}

//----------------------------------------------------------------------------
/**
 *	@brief	BMPWin解放
 *
 *	@param	outBmpWin		ビットマップ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void FreeBmpWin( GF_BGL_BMPWIN *outBmpWin )
{
	GF_BGL_BmpWinDel( outBmpWin );
	sys_FreeMemoryEz( outBmpWin );
}

//----------------------------------------------------------------------------
/**
 *	@brief	入力コントロール
 *
 *	@param	psel_ptr	ワーク
 *
 *	@return	RC_INPUT		enum参照
 */
//-----------------------------------------------------------------------------
static RC_INPUT ControlInput(FPOKE_SEL_WORK *psel_ptr)
{
	RC_INPUT rc = RCI_REQ_NONE;
	if ( !GF_TP_GetCont() ){ //（ベタ）タッチしていない場合
		//キー入力受付
		if (sys.trg & PAD_BUTTON_DECIDE){
			if (psel_ptr->Confirmation == CONF_LAST_DECIDE){	//確認状態なら、最終決定
				rc = RCI_REQ_LAST_DECIDE;
			}else if (psel_ptr->Confirmation == CONF_SELECT){	//確認状態へ
				rc = RCI_REQ_DECIDE;
			}else{												//3選択状態へ
				psel_ptr->Confirmation = CONF_SELECT;
				rc = RCI_REQ_SELECT;
			}
		}else if(sys.trg & PAD_BUTTON_CANCEL){
			if (psel_ptr->Confirmation == CONF_LAST_DECIDE){
				rc = RCI_REQ_CANCEL;
			}
		}else if (sys.trg & PAD_KEY_LEFT){
			if (psel_ptr->Confirmation != CONF_LAST_DECIDE){	//最終確認時は左右無効
				rc = RCI_REQ_REV_LEFT;
			}
		}else if(sys.trg & PAD_KEY_RIGHT){
			if (psel_ptr->Confirmation != CONF_LAST_DECIDE){	//最終確認時は左右無効
				rc = RCI_REQ_REV_RIGHT;
			}
		}
	}else if( (!sys.cont)&&GF_TP_GetTrg() ){ //キーに触れておらず、(トリガー)タッチしている場合
		//レイトレーシング
		VecFx32 near,far;
		u8 hit_no;
		fx32 range;
		//レイ取得
		NNS_G3dScrPosToWorldLine( sys.tp_x, sys.tp_y, &near, &far );
///		OS_Printf("TP：%d,%d\n",sys.tp_x, sys.tp_y);
///		OS_Printf("ニア：%x,%x,%x\n",near.x, near.y, near.z);
///		OS_Printf("ファー：%x,%x,%x\n",far.x, far.y, far.z);

		if (psel_ptr->Confirmation == CONF_LAST_DECIDE){
			range = BTN_R;
		}else{
			range = BALL_R;
		}
		//取得した直線ベクトルと3つのボールのヒット判定
		hit_no = CheckBallHit( psel_ptr->BallPos, &near, &far, range );
		if ( hit_no != BALL_NUM ){
			//ヒット
			if (psel_ptr->Confirmation == CONF_LAST_DECIDE){//確認状態
				if (hit_no == psel_ptr->FrontBallNo){	//ヒットナンバーが手前のボールナンバーと同じ
					//最終決定
					rc = RCI_REQ_LAST_DECIDE;
				}else{		//違うナンバー
					//キャンセル
					rc = RCI_REQ_CANCEL;
					//rc = GetRevReq(hit_no, psel_ptr->FrontBallNo, psel_ptr->Zoom);
				}
			}else if(psel_ptr->Confirmation == CONF_SELECT){
				if (hit_no == psel_ptr->FrontBallNo){	//ヒットナンバーが手前のボールナンバーと同じ
					//暫定決定
					rc = RCI_REQ_DECIDE;
				}else{		//違うナンバー
					rc = GetRevReq(hit_no, psel_ptr->FrontBallNo, psel_ptr->Zoom);
				}
			}else{
				if (hit_no == psel_ptr->FrontBallNo){	//ヒットナンバーが手前のボールナンバーと同じ
					psel_ptr->Confirmation = CONF_SELECT;
					rc = RCI_REQ_SELECT;
				}else{		//違うナンバー
					rc = GetRevReq(hit_no, psel_ptr->FrontBallNo, psel_ptr->Zoom);
				}
			}
		}else{
			//ボール以外
			if (psel_ptr->Confirmation == CONF_LAST_DECIDE){
				rc = RCI_REQ_CANCEL;
			}
		}
	}

	//SE
	if (rc == RCI_REQ_LAST_DECIDE){
		Snd_SePlay( SE_BTN_PUSH );
	}

	return rc;
}

//----------------------------------------------------------------------------
/**
 *	@brief	回転リクエストを返す
 *
 *	@param	inNo		タッチしたボールナンバー
 *	@param	inFrontNo	表示手前にあるボールナンバー
 *	@param	inZoom		ズーム状態
 *
 *	@return	回転リクエスト
 */
//-----------------------------------------------------------------------------
static RC_INPUT GetRevReq(const u8 inNo, const u8 inFrontNo, const ZOOM_STATE inZoom)
{

	if ( (inFrontNo+1)%BALL_NUM == inNo ){
		//時計回り
		return RCI_REQ_REV_LEFT;
	}else{
		//反時計回り
		return RCI_REQ_REV_RIGHT;
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	ボールとレイのあたり判定
 *
 *	@param	*inBallList		ボール座標リスト
 *	@param	*inNear			ニア位置ベクトル
 *	@param	*inFar			ファー位置ベクトル
 *	@param	inRange			ヒット判定半径
 *
 *	@return i	ヒットしたボールナンバー（ヒットしなかった場合はボール総数）
 */
//-----------------------------------------------------------------------------
static u8 CheckBallHit(const VecFx32 *inBallList, const VecFx32 *inNear, const VecFx32 *inFar, const fx32 inRange)
{
	u8 i;
	for(i=0;i<BALL_NUM;i++){
		fx32 len;
		const VecFx32 *vec = &inBallList[i];
		//ヒット判定
		len = BG3D_GetPointSegmentDistance2(vec, inNear, inFar);
		OS_Printf("ボール中心からの距離：%x\n",len);
		if (len <= inRange){
			OS_Printf("ヒット:%d\n",i);
			break;		//ヒット
		}
	}
	return i;
}

static void SetupSubDispPoke(FPOKE_SEL_WORK *psel_ptr)
{
	int i;
	ARCHANDLE *handle;
	POKE_ACT *poke_act;

	//カットインのアーカイブを使用する
	handle = ArchiveDataHandleOpen(ARC_FIELD_CUTIN_GRA, psel_ptr->HeapID);
	poke_act = &psel_ptr->PokeAct;

	for(i=0;i<BALL_NUM;i++){
		poke_act->ResObjTbl[i][CLACT_U_CHAR_RES] = CLACT_U_ResManagerResAddArcChar_ArcHandle(
				poke_act->ResMan[CLACT_U_CHAR_RES], handle,
				NARC_field_cutin_poke_oam_NCGR, FALSE, i,
				NNS_G2D_VRAM_TYPE_2DSUB, psel_ptr->HeapID );
		poke_act->ResObjTbl[i][CLACT_U_PLTT_RES] = CLACT_U_ResManagerResAddArcPltt_ArcHandle(
				poke_act->ResMan[CLACT_U_PLTT_RES], handle,
				NARC_field_cutin_dp_boy01_NCLR, FALSE, i,
				NNS_G2D_VRAM_TYPE_2DSUB, CLACT_U_PLTT_RES, psel_ptr->HeapID );
		poke_act->ResObjTbl[i][CLACT_U_CELL_RES] = CLACT_U_ResManagerResAddArcKindCell_ArcHandle(
				poke_act->ResMan[CLACT_U_CELL_RES], handle,
				NARC_field_cutin_poke_oam_NCER, FALSE, i,
				CLACT_U_CELL_RES, psel_ptr->HeapID );
		poke_act->ResObjTbl[i][CLACT_U_CELLANM_RES] = CLACT_U_ResManagerResAddArcKindCell_ArcHandle(
				poke_act->ResMan[CLACT_U_CELLANM_RES], handle,
				NARC_field_cutin_hidenlight_NANR, FALSE, i,
				CLACT_U_CELLANM_RES, psel_ptr->HeapID );

		{
			//モンスターナンバー・性別・レアを取得
			int monsno = PokeParaGet(psel_ptr->PokeParam[i], ID_PARA_monsno, NULL);
			int poke_sex = PokeParaGet(psel_ptr->PokeParam[i], ID_PARA_sex, NULL);
			u8 rare = PokeRareGet(psel_ptr->PokeParam[i]);
			//最後の引数は、FormNoと個性乱数です by soga 2006.05.01
			PokeGraArcDataGet( &poke_act->SpriteArc, monsno, poke_sex, PARA_FRONT, rare, NULL, NULL );
		}

		poke_act->PokeChar[i] = ChangesInto_BattlePokeData_Alloc(poke_act->SpriteArc.arc_no, poke_act->SpriteArc.index_chr, psel_ptr->HeapID);
		poke_act->PokePal[i] = ChangesInto_BattlePokePalData_Alloc( poke_act->SpriteArc.arc_no, poke_act->SpriteArc.index_pal, psel_ptr->HeapID);

		SetPokeGra( poke_act->ResMan[CLACT_U_CHAR_RES], poke_act->ResMan[CLACT_U_PLTT_RES], poke_act->PokeChar[i], poke_act->PokePal[i], i );

		SetPokeActor( poke_act, i, psel_ptr->HeapID);
	}

	ArchiveDataHandleClose(handle);
}

//--------------------------------------------------------------
/**
 * リソースマネージャポケモンキャラVRAM転送
 * @param	man_obj_ptr		ＯＢＪリソースマネージャ
 * @param	man_pal_ptr		パレットリソースマネージャ
 * @param	chr_buf			キャラバッファ
 * @param	pal_buf			パレットバッファ
 *
 * @return	none
 */
//--------------------------------------------------------------
static void SetPokeGra( CLACT_U_RES_MANAGER_PTR man_obj_ptr,
						CLACT_U_RES_MANAGER_PTR man_pal_ptr,
						void *chr_buf, void *pal_buf,
						const u8 inCode)
{
	int transSize;
	u32 image_vram,palette_vram;
	CLACT_U_RES_OBJ_PTR res_obj_ptr;
	CLACT_U_RES_OBJ_PTR res_pal_ptr;
	NNSG2dImageProxy *image_proxy;
	const NNSG2dImagePaletteProxy *palette_proxy;

	res_obj_ptr = CLACT_U_ResManagerGetIDResObjPtr( man_obj_ptr, inCode );
	res_pal_ptr = CLACT_U_ResManagerGetIDResObjPtr( man_pal_ptr, inCode );

	//ＶＲＡＭ転送
	CLACT_U_CharManagerSetAreaCont( res_obj_ptr );
	CLACT_U_PlttManagerSetCleanArea( res_pal_ptr );

	image_proxy = CLACT_U_CharManagerGetProxy( res_obj_ptr );
	palette_proxy = CLACT_U_PlttManagerGetProxy( res_pal_ptr, image_proxy );

	image_vram = NNS_G2dGetImageLocation( image_proxy, NNS_G2D_VRAM_TYPE_2DSUB );
	palette_vram = NNS_G2dGetImagePaletteLocation( palette_proxy, NNS_G2D_VRAM_TYPE_2DSUB );

	transSize = (32*10)*10;	//32byte x10 y10
	DC_FlushRange(chr_buf,transSize);
	GXS_LoadOBJ( chr_buf, image_vram, transSize );

	transSize = 32;	//32byte
	DC_FlushRange( pal_buf, transSize );
	GXS_LoadOBJPltt( pal_buf, palette_vram, transSize );	//32byte 1Palette
}

//----------------------------------------------------------------------------
/**
 *	@brief	セルアクターをセット
 *
 *	@param	*ptr			ポケモンアクター
 *	@param	inCode			識別コード
 *	@param	int inHeapID 	ヒープＩＤ
 *
 *	@return
 */
//-----------------------------------------------------------------------------
static void SetPokeActor( POKE_ACT *ptr, const u8 inCode, const int inHeapID )
{
	int i;
	CLACT_HEADER			cl_act_header;

	// セルアクターヘッダ作成
	CLACT_U_MakeHeader(	&cl_act_header,
						inCode,inCode,inCode,inCode,
						CLACT_U_HEADER_DATA_NONE,
						CLACT_U_HEADER_DATA_NONE,
						0, 0,
						ptr->ResMan[CLACT_U_CHAR_RES],
						ptr->ResMan[CLACT_U_PLTT_RES],
						ptr->ResMan[CLACT_U_CELL_RES],
						ptr->ResMan[CLACT_U_CELLANM_RES],
						NULL,NULL);

	{
		//登録情報格納
		CLACT_ADD add;

		add.ClActSet	= ptr->ClactSet;
		add.ClActHeader	= &cl_act_header;

		add.mat.x		= 0;//FX32_CONST(32) ;
		add.mat.y		= 0;//FX32_CONST(96) ;		//画面は上下連続している
		add.mat.z		= 0;
		add.sca.x		= FX32_ONE;
		add.sca.y		= FX32_ONE;
		add.sca.z		= FX32_ONE;
		add.rot			= 0;
		add.pri			= 0;
		add.DrawArea	= NNS_G2D_VRAM_TYPE_2DSUB;
		add.heap		= inHeapID;

		//セルアクター表示開始

		add.mat.x = FX32_ONE * (256/2);
		add.mat.y = FX32_ONE * ((192/2) + 192);
		ptr->ClActWork[inCode] = CLACT_Add(&add);
		CLACT_SetAnmFlag(ptr->ClActWork[inCode],0);
		CLACT_AnmChg( ptr->ClActWork[inCode], 0 );
		CLACT_SetDrawFlag(ptr->ClActWork[inCode], 0);	//非表示
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	画面手前ポケモン表示
 *
 *	@param	*psel_ptr		ワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void DispFrontBallPoke(FPOKE_SEL_WORK *psel_ptr)
{
	HideAllPoke(&psel_ptr->PokeAct);
	//手前ポケ表示
	CLACT_SetDrawFlag(psel_ptr->PokeAct.ClActWork[ psel_ptr->FrontBallNo ], 1);
}

//----------------------------------------------------------------------------
/**
 *	@brief	全ポケ非表示
 *
 *	@param	*pPokeAct 		ポケモンアクターポインタ
 *
 *	@return none
 */
//-----------------------------------------------------------------------------
static void HideAllPoke(POKE_ACT *pPokeAct )
{
	int i;
	for(i=0;i<BALL_NUM;i++){
		CLACT_SetDrawFlag(pPokeAct->ClActWork[i], 0);
	}
}

//ボールと1対1画面へ移行
static BOOL RotFrontBall(FPOKE_SEL_WORK *psel_ptr, const int inOrgAng, const int inDstAng)
{
	u16 rot;
	u32 no = psel_ptr->FrontBallNo;
	psel_ptr->SelBallRotSync++;
	rot = ChangeAngle(&inOrgAng, &inDstAng, psel_ptr->SelBallRotSync, SEL_BALL_ROT_SYNC );
	OS_Printf("rott:%x:%x\n",rot,inDstAng);
	{
		MtxFx33	calc;
		const fx32 r = 13.453124*FX32_ONE;		//<<IMD見たから正確なハズ
		VecFx32 ball_btm = {0, BALL_OFS, TURN_TABLE_R};
		VecFx32 ball_core = {0, BALL_OFS, TURN_TABLE_R};
		ball_core.y += r;
		//ボール底の位置ベクトルを回転軸ベクトルのオフセット分平行移動したベクトル
		VEC_Subtract( &ball_btm, &ball_core, &ball_btm);
		//X軸回転
		MTX_RotX33( &calc, FX_SinIdx( rot ), FX_CosIdx( rot ) );
		MTX_MultVec33(&ball_btm, &calc, &ball_btm);
		//平行移動したぶんを戻す
		VEC_Add( &ball_btm, &ball_core, &ball_btm);
		//トランス
		Set3DObjTrans(&psel_ptr->ObjData[POKESELECT_BALL1+no],
				ball_btm.x, ball_btm.y, ball_btm.z );
	}
	//ローテーション
	psel_ptr->ObjData[POKESELECT_BALL1+no].RotX = rot;

	if (psel_ptr->SelBallRotSync >= SEL_BALL_ROT_SYNC){
		psel_ptr->SelBallRotSync = 0;
		return TRUE;
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	アングル変更関数
 *
 *	@param	*org			変更前パラメータ
 *	@param	*dst			変更後パラメータ
 *	@param	u8 now_sync		現在シンク
 *	@param	u8 total_sync 	総シンク数
 *
 *	@return rot				アングル
 */
//-----------------------------------------------------------------------------
static u16 ChangeAngle(const int *org, const int *dst, const u8 now_sync, const u8 total_sync )
{
	u16 rot;
	u16 def;
	int tmp;

	//開始アングルと最終目的アングルの差分を取る
	if ( (*dst) >= (*org)  ){
		def = (*dst) - (*org);
		tmp = (def*now_sync)/total_sync;
	}else{
		def = (*org) - (*dst);
		tmp = -( (def*now_sync)/total_sync);
	}

	//現在アングルの計算
	rot = (*org) + tmp;
	return rot;
}


///////////////////////////////////////////////////////////////////////////////////////////////////
//カメラデバッグ関連
#ifdef PM_DEBUG

#define ANGLE_MOVE	(32)
static void DebugPritnfCameraInfo(GF_CAMERA_PTR camera_ptr)
{
	CAMERA_ANGLE angle;
	u16 angle_x;

	angle = GFC_GetCameraAngle(camera_ptr);
	//仰角⇒地面からの傾きに変換
	angle_x = -angle.x;

	OS_Printf("距離：%x\n",GFC_GetCameraDistance(camera_ptr));
	OS_Printf("アングル：%x\n",angle.x);
	OS_Printf("パース：%x\n",GFC_GetCameraPerspWay(camera_ptr));
	OS_Printf("ニア・ファー：%d_%d\n",
			GFC_GetCameraNear(camera_ptr)/FX32_ONE, GFC_GetCameraFar(camera_ptr)/FX32_ONE);
	{
		//バインドターゲットとの差分
		VecFx32 look_at = GFC_GetLookTarget(camera_ptr);
		const VecFx32 *bind = GFC_GetBindTargetVecPtr(camera_ptr);

		OS_Printf("オフセット：%x,%x,%x\n",
				look_at.x-bind->x, look_at.y-bind->y, look_at.z-bind->z);
	}
}

static void DebugCameraInput(GF_CAMERA_PTR camera_ptr)
{
	u8 view;
	fx32 dist;
	u16 persp_way;

	CAMERA_ANGLE angle = {0,0,0,0};
	VecFx32 move = {0,0,0};

	if (1){
		if (sys.cont & PAD_BUTTON_B){			//カメラ回転（公転）
			if (sys.cont & PAD_KEY_UP){
				angle.x = ANGLE_MOVE;
				GFC_AddCameraAngleRev(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				angle.x = -ANGLE_MOVE;
				GFC_AddCameraAngleRev(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_LEFT){
				angle.y = -ANGLE_MOVE;
				GFC_AddCameraAngleRev(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_RIGHT){
				angle.y = ANGLE_MOVE;
				GFC_AddCameraAngleRev(&angle,camera_ptr);
			}
		}
		else if (sys.cont & PAD_BUTTON_Y){		//カメラ回転（自転）
			if (sys.cont & PAD_KEY_UP){
				angle.x = ANGLE_MOVE;
				GFC_AddCameraAngleRot(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				angle.x = -ANGLE_MOVE;
				GFC_AddCameraAngleRot(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_LEFT){
				angle.y = ANGLE_MOVE;
				GFC_AddCameraAngleRot(&angle,camera_ptr);
			}else if (sys.cont & PAD_KEY_RIGHT){
				angle.y = -ANGLE_MOVE;
				GFC_AddCameraAngleRot(&angle,camera_ptr);
			}
		}
		else if (sys.cont & PAD_BUTTON_A){
			if (sys.cont & PAD_KEY_UP){			//カメラズームアウト
				persp_way = GFC_GetCameraPerspWay(camera_ptr);
				if (persp_way+64<0x4000){
					GFC_AddCameraPerspWay(64,camera_ptr);
				}
			}else if (sys.cont & PAD_KEY_DOWN){	//カメラズームイン
				persp_way = GFC_GetCameraPerspWay(camera_ptr);
				if ((u16)(persp_way-64)>0x0000){
					GFC_AddCameraPerspWay(-64,camera_ptr);
				}
			}else if (sys.cont & PAD_KEY_LEFT){
				GFC_AddCameraPerspWay(64,camera_ptr);
				persp_way = GFC_GetCameraPerspWay(camera_ptr);
				//カメラの中心にある2D画像が、崩れずに表示できる距離を求める
				//つぶれずに表示するためには、1Dot　＝　1Unitで計算すればよい
				//カメラが画面中心を見つめるとき、画面半分のサイズは、96Dot
				//表示させたい、カメラのパースを考え、96Dot　＝　96Unitになる距離にすればよい
				dist = FX_Div( FX_Mul( FX_CosIdx( persp_way ), FX_F32_TO_FX32(96) ),
									 FX_SinIdx( persp_way ));
				GFC_SetCameraDistance(dist,camera_ptr);
			}else if(sys.cont & PAD_KEY_RIGHT){
				GFC_AddCameraPerspWay(-64,camera_ptr);
				persp_way = GFC_GetCameraPerspWay(camera_ptr);
				//カメラの中心にある2D画像が、崩れずに表示できる距離を求める
				//つぶれずに表示するためには、1Dot　＝　1Unitで計算すればよい
				//カメラが画面中心を見つめるとき、画面半分のサイズは、96Dot
				//表示させたい、カメラのパースを考え、96Dot　＝　96Unitになる距離にすればよい
				dist = FX_Div( FX_Mul( FX_CosIdx( persp_way ), FX_F32_TO_FX32(96) ),
									 FX_SinIdx( persp_way ));
				GFC_SetCameraDistance(dist,camera_ptr);
			}
		}
		else if (sys.cont & PAD_BUTTON_X){
			fx32 shift;
			if(sys.cont & PAD_BUTTON_R){
				shift = (FX32_ONE*1)/10;
			}else{
				shift = FX32_ONE;
			}
			if (sys.cont & PAD_KEY_UP){
				move.z -= shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				move.z += shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}else if (sys.cont & PAD_KEY_LEFT){
				move.x -= shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}else if (sys.cont & PAD_KEY_RIGHT){
				move.x += shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}
		}else if (sys.cont & PAD_BUTTON_START){
			fx32 shift;
			if(sys.cont & PAD_BUTTON_R){
				shift = (FX32_ONE*1)/10;
			}else{
				shift = FX32_ONE;
			}
			if (sys.cont & PAD_KEY_UP){
				move.y += shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				move.y -= shift;
				GFC_ShiftCamera(&move,camera_ptr);
			}
		}else if(sys.cont & PAD_BUTTON_R){
			fx32 near,far;
			if (sys.cont & PAD_KEY_UP){
				far = GFC_GetCameraFar(camera_ptr);
				near = GFC_GetCameraNear(camera_ptr);
				far += FX32_ONE;
				OS_Printf("far=%d\n",far/FX32_ONE);
				GFC_SetCameraClip(near,far,camera_ptr);
			}else if (sys.cont & PAD_KEY_DOWN){
				far = GFC_GetCameraFar(camera_ptr);
				near = GFC_GetCameraNear(camera_ptr);
				far -= FX32_ONE;
				OS_Printf("far=%d\n",far/FX32_ONE);
				GFC_SetCameraClip(near,far,camera_ptr);
			}else if(sys.cont & PAD_KEY_RIGHT){
				far = GFC_GetCameraFar(camera_ptr);
				near = GFC_GetCameraNear(camera_ptr);
				near += FX32_ONE;
				OS_Printf("near=%d\n",near/FX32_ONE);
				GFC_SetCameraClip(near,far,camera_ptr);
			}else if(sys.cont & PAD_KEY_LEFT){
				far = GFC_GetCameraFar(camera_ptr);
				near = GFC_GetCameraNear(camera_ptr);
				near -= FX32_ONE;
				OS_Printf("near=%d\n",near/FX32_ONE);
				GFC_SetCameraClip(near,far,camera_ptr);
			}
		}
		else if (sys.cont & PAD_KEY_UP){	//カメラを遠ざける
			GFC_AddCameraDistance(FX32_ONE,camera_ptr);
		}else if (sys.cont & PAD_KEY_DOWN){	//カメラを近づける
			GFC_AddCameraDistance(-FX32_ONE,camera_ptr);
		}
	}
}

#endif //PM_DEBUG


#ifdef ttt
#define ARRAY_MAX	(10)

int gOutPutNum;
int gArray[ARRAY_MAX];

void InitArray()
{
	int i;
	for(i=0;i<ARRAY_NUM;i++){
		gArray[i] = i;
	}
	gOutPutNum = 0;
}

int GetValue()
{
	int array_num;	//現在の配列要素数
	int idx;		//取り出す配列のインデックス
	int val;		//出力値

	//配列のオーバー参照回避
	if (gOutPutNum >= ARRAY_MAX){
		return 0;
	}

	array_num = ARRAY_MAX - gOutPutNum;
	idx = Rand(array_num)-1;
	val = gArray[idx];

	//取り出す配列インデックスが配列末尾以外なら、取り出した場所を配列末尾の値で上書き
	if (idx != array_num-1){
		gArray[idx] = gArray[ array_num-1 ];
	}
	gOutPutNum++;

	return val;
}
#endif